Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions samples/da-ristorante-api-csharp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# TeamsFx files
M365Agent/appPackage/build
M365Agent/env/.env.*.user
M365Agent/env/.env.local

# User-specific files
*.user

# Build results
[Dd]ebug/
[Rr]elease/
x64/
x86/
[Bb]in/
[Oo]bj/
6 changes: 6 additions & 0 deletions samples/da-ristorante-api-csharp/DaRistoranteApi.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Solution>
<Project Path="DaRistoranteApi/DaRistoranteApi.csproj" />
<Project Path="M365Agent/M365Agent.atkproj" Type="a9e3f50b-275e-4af7-adce-8be12d41e305">
<Deploy />
</Project>
</Solution>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<RootNamespace>DaRistoranteApi</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.50.0-preview1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.5" />
</ItemGroup>

<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>

<ItemGroup>
<Content Include="data.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>
19 changes: 19 additions & 0 deletions samples/da-ristorante-api-csharp/DaRistoranteApi/MenuData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using DaRistoranteApi.Models;
using System.Text.Json;

namespace DaRistoranteApi
{
public static class MenuData
{
private static readonly List<Dish> _dishes;

static MenuData()
{
var dataPath = Path.Combine(AppContext.BaseDirectory, "data.json");
var json = File.ReadAllText(dataPath);
_dishes = JsonSerializer.Deserialize<List<Dish>>(json) ?? new List<Dish>();
}

public static List<Dish> GetDishes() => _dishes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Text.Json.Serialization;

namespace DaRistoranteApi.Models
{
public class Dish
{
[JsonPropertyName("id")]
public int Id { get; set; }

[JsonPropertyName("name")]
public string Name { get; set; }

[JsonPropertyName("description")]
public string Description { get; set; }

[JsonPropertyName("image_url")]
public string ImageUrl { get; set; }

[JsonPropertyName("price")]
public double Price { get; set; }

[JsonPropertyName("allergens")]
public List<string> Allergens { get; set; } = new();

[JsonPropertyName("type")]
public string Type { get; set; }

[JsonPropertyName("course")]
public string Course { get; set; }
}

public class OrderedDish
{
[JsonPropertyName("name")]
public string Name { get; set; }

[JsonPropertyName("quantity")]
public int Quantity { get; set; }
}

public class Order
{
[JsonPropertyName("dishes")]
public List<OrderedDish> Dishes { get; set; }
}
}
7 changes: 7 additions & 0 deletions samples/da-ristorante-api-csharp/DaRistoranteApi/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.Build();

host.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"profiles": {
"Start Project": {
"commandName": "Project",
"commandLineArgs": "host start --port 5130 --pause-on-error",
"dotnetRunMessages": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"hotReloadProfile": "aspnetcore"
}
}
}
113 changes: 113 additions & 0 deletions samples/da-ristorante-api-csharp/DaRistoranteApi/RistoranteApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Net;
using System.Text.Json;

namespace DaRistoranteApi
{
public class RistoranteApi
{
private readonly ILogger _logger;

public RistoranteApi(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<RistoranteApi>();
}

[Function("dishes")]
public async Task<HttpResponseData> GetDishesAsync(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a dishes request.");

var allDishes = MenuData.GetDishes();
var filtered = allDishes.AsEnumerable();

var name = req.Query["name"];
if (!string.IsNullOrEmpty(name))
{
filtered = filtered.Where(d => d.Name.Contains(name, StringComparison.OrdinalIgnoreCase));
}

var course = req.Query["course"];
if (!string.IsNullOrEmpty(course))
{
filtered = filtered.Where(d => d.Course == course);
}

var type = req.Query["type"];
if (!string.IsNullOrEmpty(type))
{
filtered = filtered.Where(d => d.Type == type);
}

var allergensParam = req.Query["allergens"];
if (!string.IsNullOrEmpty(allergensParam))
{
var allergens = allergensParam.Split(',', StringSplitOptions.RemoveEmptyEntries);
filtered = filtered.Where(d => allergens.All(a => !d.Allergens.Contains(a)));
}

var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(new { dishes = filtered.ToList() });
return response;
}

[Function("orders")]
public async Task<HttpResponseData> PlaceOrderAsync(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed an orders request.");

Models.Order order;
try
{
order = await JsonSerializer.DeserializeAsync<Models.Order>(req.Body);
}
catch (JsonException)
{
var badResponse = req.CreateResponse(HttpStatusCode.BadRequest);
await badResponse.WriteAsJsonAsync(new { message = "Invalid JSON format" });
return badResponse;
}

if (order?.Dishes == null || order.Dishes.Count == 0)
{
var badResponse = req.CreateResponse(HttpStatusCode.BadRequest);
await badResponse.WriteAsJsonAsync(new { message = "Invalid order format" });
return badResponse;
}

var allDishes = MenuData.GetDishes();
double totalPrice = 0;

foreach (var orderedDish in order.Dishes)
{
var match = allDishes.FirstOrDefault(d =>
d.Name.Contains(orderedDish.Name, StringComparison.OrdinalIgnoreCase));

if (match == null)
{
_logger.LogError("Invalid dish: {DishName}", orderedDish.Name);
var badResponse = req.CreateResponse(HttpStatusCode.BadRequest);
await badResponse.WriteAsJsonAsync(new { message = "One or more invalid dishes" });
return badResponse;
}

totalPrice += match.Price * orderedDish.Quantity;
}

var orderId = Random.Shared.Next(0, 10000);

var response = req.CreateResponse(HttpStatusCode.Created);
await response.WriteAsJsonAsync(new
{
order_id = orderId,
status = "confirmed",
total_price = totalPrice
});
return response;
}
}
}
Loading