<file_sep>﻿using Microsoft.EntityFrameworkCore;

namespace WiredBrainCoffee.MinApi
{

    public class OrderDbContext : DbContext
    {
        public OrderDbContext(DbContextOptions options) : base(options) { }

        public DbSet<Order> Orders => Set<Order>();

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Order>().HasData(
                new Order
                {
                    Id = 1,
                    Description = "A coffee order",
                    PromoCode = "Wired123",
                    Created = DateTime.Now,
                    OrderNumber = 100,
                    Total = 25
                },
                new Order
                {
                    Id = 2,
                    Description = "A food order",
                    PromoCode = "Wired123",
                    Created = DateTime.Now,
                    OrderNumber = 125,
                    Total = 35
                }
            );

        }
    }
}
<file_sep>﻿using Microsoft.AspNetCore.Mvc.RazorPages;

namespace WiredBrainCoffee.Pages
{
    public class ItemModel : PageModel
    {
        public string Message { get; set; }

        public void OnGet(int id)
        {
            Message = "The id is " + id;
        }
    }
}<file_sep>﻿using WiredBrainCoffee.Models;

namespace WiredBrainCoffee.UI.Services
{
    public static class EmailService
    {
        public static void SendEmail(Contact contact)
        {
            // Todo
        }

        public static void SendEmail(string address)
        {
            // Todo
        }
    }
}
<file_sep># RazorPages Demo
A demo of a Razor Pages only web site
<file_sep>﻿using System;

namespace WiredBrainCoffee.Models
{
    public enum CreamerOptions
    {
        None,
        Light,
        Regular,
        Heavy
    }
}
<file_sep>﻿using System.Net.Http.Json;
using WiredBrainCoffee.Models;

namespace WiredBrainCoffee.UI.Services
{
    public class OrderService : IOrderService
    {
        private readonly HttpClient http;

        public OrderService(HttpClient http)
        {
            this.http = http;
        }

        public async Task<List<Order>> GetOrders()
        {
            var orders = await http.GetFromJsonAsync<List<Order>>("orders");
            return orders;
        }
    }
}
<file_sep>using Microsoft.EntityFrameworkCore;
using WiredBrainCoffee.MinApi;

var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("Orders") ?? "Data Source=Orders.db";

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddScoped<IOrderService, OrderService>();
builder.Services.AddSqlite<OrderDbContext>(connectionString);

builder.Services.AddCors(options =>
{
    options.AddPolicy("Default", builder =>
    {
        builder.AllowAnyOrigin();
    });
});
builder.Services.AddHttpClient();

var app = builder.Build();

await CreateDb(app.Services, app.Logger);

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseCors();

app.MapGet("/order-status", async (IHttpClientFactory factory) =>
{
    var client = factory.CreateClient();
    var response = await client.GetFromJsonAsync<OrderSystemStatus>("https://wiredbraincoffee.azurewebsites.net/api/OrderSystemStatus");

    return Results.Ok(response);
})
.WithName("Get system status");

app.MapGet("/orders/{id}", (int id, IOrderService orderService) =>
{
    var order = orderService.GetOrderById(id);

    if (order == null)
    {
        return Results.NotFound();
    }

    return Results.Ok(order);
})
.WithName("Get order by id");


app.MapGet("/orders", (IOrderService orderService) =>
{
    return Results.Ok(orderService.GetOrders());
})
.WithName("Get orders");


app.MapPost("/orders", (Order newOrder, IOrderService orderService) =>
{
    var createdOrder = orderService.AddOrder(newOrder);

    return Results.Created($"/orders/{createdOrder.Id}", createdOrder);
})
.WithName("Create order");


app.MapPut("/orders/{id}", (int id, Order updatedOrder, IOrderService orderService) =>
{
    orderService.UpdateOrder(id, updatedOrder);

    return Results.NoContent();
})
.WithName("Update Order");


app.MapDelete("/orders/{id}", (int id, IOrderService orderService) =>
{
    orderService.DeleteOrder(id);

    return Results.Ok();
})
.WithName("Delete Order");

app.Run();

async Task CreateDb(IServiceProvider services, ILogger logger)
{
    using var db = services.CreateScope().ServiceProvider.GetRequiredService<OrderDbContext>();
    await db.Database.MigrateAsync();
}

<file_sep>﻿namespace WiredBrainCoffee.MinApi
{
    public class Order
    {
        public int Id { get; set; }
        public string Description { get; set; }
        public int OrderNumber { get; set; }
        public string PromoCode { get; set; }
        public DateTime Created { get; set; }
        public decimal Total { get; set; }
    }
}
<file_sep>﻿using Microsoft.EntityFrameworkCore.Migrations;
using System;

#nullable disable

namespace WiredBrainCoffee.MinApi.Migrations
{
    public partial class InitialCreate : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Orders",
                columns: table => new
                {
                    Id = table.Column<int>(type: "INTEGER", nullable: false)
                        .Annotation("Sqlite:Autoincrement", true),
                    Description = table.Column<string>(type: "TEXT", nullable: false),
                    OrderNumber = table.Column<int>(type: "INTEGER", nullable: false),
                    PromoCode = table.Column<string>(type: "TEXT", nullable: false),
                    Created = table.Column<DateTime>(type: "TEXT", nullable: false),
                    Total = table.Column<decimal>(type: "TEXT", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Orders", x => x.Id);
                });

            migrationBuilder.InsertData(
                table: "Orders",
                columns: new[] { "Id", "Created", "Description", "OrderNumber", "PromoCode", "Total" },
                values: new object[] { 1, DateTime.Now, "A coffee order", 100, "Wired123", 25m });

            migrationBuilder.InsertData(
                table: "Orders",
                columns: new[] { "Id", "Created", "Description", "OrderNumber", "PromoCode", "Total" },
                values: new object[] { 2, DateTime.Now, "A food order", 125, "Wired123", 35m });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Orders");
        }
    }
}
<file_sep>﻿using Microsoft.AspNetCore.Mvc;

namespace WiredBrainCoffee.Api.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class OrdersController : ControllerBase
    {
        private readonly ILogger<OrdersController> _logger;

        public OrdersController(ILogger<OrdersController> logger)
        {
            _logger = logger;
        }

        [HttpGet("history")]
        public IActionResult Get()
        {
            // Do this in minimal API?

            return Ok();
        }
    }
}
<file_sep>﻿using System;

namespace WiredBrainCoffee.Models
{
    public enum ContactReason
    {
        Refund,
        Order,
        Quality,
        Feedback,
        Staff
    }
}
<file_sep>﻿using WiredBrainCoffee.Models;

namespace WiredBrainCoffee.Services
{
    public interface IMenuService
    {
        List<MenuItem> GetMenuItems();
    }
}<file_sep>﻿namespace WiredBrainCoffee.MinApi
{
    public class OrderService : IOrderService
    {
        private OrderDbContext _context;

        public OrderService(OrderDbContext context)
        {
            _context = context;
        }

        public List<Order> GetOrders()
        {
            return _context.Orders.ToList();
        }

        public Order GetOrderById(int id)
        {
            return _context.Orders.FirstOrDefault(x => x.Id == id);
        }

        public Order AddOrder(Order order)
        {
            _context.Orders.Add(order);
            _context.SaveChanges();

            return order;
        }

        public void UpdateOrder(int id, Order newOrder)
        {
            var order = _context.Orders.FirstOrDefault(x => x.Id == id);

            order.Description = newOrder.Description;
            order.PromoCode = newOrder.PromoCode;
            order.Total = newOrder.Total;
            order.OrderNumber = newOrder.OrderNumber;
            _context.SaveChanges();
        }

        public void DeleteOrder(int id)
        {
            var order = _context.Orders.FirstOrDefault(x => x.Id == id);
            _context.Orders.Remove(order);

            _context.SaveChanges();
        }
    }

    public interface IOrderService
    {
        Order AddOrder(Order order);
        void DeleteOrder(int id);
        Order GetOrderById(int id);
        List<Order> GetOrders();
        void UpdateOrder(int id, Order newOrder);
    }
}
<file_sep>﻿namespace WiredBrainCoffee.MinApi
{
    public class OrderSystemStatus
    {
        public string Status { get; set; }
        public DateTime ScheduledUpdate { get; set; }
        public DateTime UpTime { get; set; }
        public string Version { get; set; }
    }
}
<file_sep>﻿using WiredBrainCoffee.Models;

namespace WiredBrainCoffee.UI.Services
{
    public interface IOrderService
    {
        Task<List<Order>> GetOrders();
    }
}<file_sep>using Microsoft.AspNetCore.HttpLogging;
using WiredBrainCoffee.Api.Hubs;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddSignalR();
builder.Services.AddControllers();
builder.Services.AddRazorPages();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddHttpLogging(httpLogging =>
{
    httpLogging.LoggingFields = HttpLoggingFields.All;
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.Use(async (context, next) =>
{
    context.Request.Headers.AcceptLanguage = "C# Forever";
    context.Response.Headers.XPoweredBy = "ASPNETCORE 6.0";
    await next.Invoke(context);
});

app.UseHttpLogging();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.MapHub<ChatHub>("/chathub");
app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

app.Run();
<file_sep>using Blazored.Modal;
using Blazorise;
using Blazorise.Bootstrap;
using Blazorise.Icons.FontAwesome;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using WiredBrainCoffee.UI;
using WiredBrainCoffee.UI.Components;
using WiredBrainCoffee.UI.Services;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.RootComponents.RegisterForJavaScript<GlobalAlert>(identifier: "globalAlert");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

builder.Services.AddBlazoredModal();
builder.Services.AddBlazorise(options =>
{
})
  .AddBootstrapProviders()
  .AddFontAwesomeIcons();

builder.Services.AddHttpClient<IMenuService, MenuService>(client =>
    client.BaseAddress = new Uri("https://localhost:7024/"));
builder.Services.AddHttpClient<IContactService, ContactService>(client =>
    client.BaseAddress = new Uri("https://localhost:7024/"));
builder.Services.AddHttpClient<IOrderService, OrderService>(client =>
    client.BaseAddress = new Uri("https://localhost:9991/"));

var host = builder.Build();

await host.RunAsync();
