Skip to content

.NET library extending functionality for web applications. Source generators for .Net.Sdk that implement the MVC functionality for Asp with NativeAOT support.

License

Notifications You must be signed in to change notification settings

AlexMacocian/Net.Sdk.Web.Extensions

Repository files navigation

Net.Sdk.Web.Extensions

.NET library extending functionality for web applications

Features

MVC Source Generators

Net.Sdk.Web.Extensions provides a set of source generators to replicate the MVC functionality of Asp while being compatible with NativeAOT compilation.

Usage

  1. Add the Net.Sdk.Web.Extensions.SourceGenerators package to your project
  2. Create a controller class
[GenerateController("api/v1/accounts")]
public sealed class AccountsController(
    IAccountService accountService)
{
    private readonly IAccountService accountService = accountService;

    [GenerateGet("{accountId}")]
    [RouteFilter<AuthenticatedFilter>]
    public async Task<IResult> GetAccount(HttpContext context, [FromRoute] string accountId, CancellationToken cancellationToken)
    {
        var account = await this.accountService.GetAccountById(accountId, cancellationToken);
        if (account is null)
        {
            return Results.NotFound();
        }

        return Results.Ok(account);
    }

    [GeneratePost]
    public async Task<IResult> PostAccount([FromBody] PostAccountRequest request, CancellationToken cancellationToken)
    {
        if (await this.accountService.CreateAccount(request.Email, request.Email, request.Password, cancellationToken))
        {
            return Results.Created();
        }

        return Results.BadRequest();
    }
}
  1. Register the routes in the WebApplicationBuilder using WithRoutes() extension. This extension is generated by the source generator and is available under the Net.Sdk.Web namespace in WebApplicationBuilderExtensions class.
builder.WithRoutes();
  1. Use the routes in your WebApplication class using UseRoutes() extension. This extension is generated by the source generator and is available under the Net.Sdk.Web namespace in WebApplicationExtensions class.
app.UseRoutes();

Functionality

  • GenerateController attribute allows you to define a controller class and its route.
  • GenerateGet, GeneratePost, GeneratePut, GenerateDelete attributes allow you to define the HTTP methods and their routes.
  • FromRoute, FromBody, FromQuery attributes allow you to define the parameters of the methods.
  • RouteFilter attribute allows you to define the filters for the methods. Filters must be of type Microsoft.AspNetCore.Http.IEndpointFilter.
  • HttpContext can be accessed by requesting it as a parameter of your route method. The generator will automatically fetch it from the context and pass it to your method.
  • Controllers are registered as services in the DI container, so you can inject any service into them.
  • There is no restriction on the modifiers of your controllers. You can freely use inheritance for shared functionality between controllers.

Better WebSocket support

Net.Sdk.Web.Extensions provides a streamlined implementation of WebSockets to be used in a web app, in a syntax similar to Asp Mvc

Integration into WebApplication

var builder = WebApplication.CreateSlimBuilder(args);
var app = builder.Build();
app.MapWebSocket<CustomRoute>("custom-route");

Message mapping

Define your request

[WebSocketConverter<JsonWebSocketMessageConverter<CustomRequest>, CustomRequest>]
public class CustomRequest{
}

Define your response

[WebSocketConverter<JsonWebSocketMessageConverter<CustomResponse>, CustomResponse>]
public class CustomResponse{
}

Implement your WebSocketRoute

public class CustomRoute : WebSocketRouteBase<CustomRequest, CustomResponse>
{
    public override Task SocketAccepted(CancellationToken cancellationToken)
    {
        return base.SocketAccepted(cancellationToken);
    }

    public override Task SocketClosed()
    {
        return base.SocketClosed();
    }

    public override async Task ExecuteAsync(CustomRequest? request, CancellationToken cancellationToken)
    {
        await this.SendMessage(new BotResponse(), cancellationToken);
    }
}

Support for IActionFilter

Decorate your CustomRoute with filters that get executed the same way as in a AspNetCore web app Both IActionFilter and IAsyncActionFilter are supported

[ServiceFilter<CustomFilter>]
public class CustomRoute : WebSocketRouteBase<CustomRequest, CustomResponse>

Custom message converters

If you need specialized converters, implement your own WebSocketMessageConverter<T>

Request tracing using CorrelationVectors

Integration into WebApplication

var builder = WebApplication.CreateSlimBuilder(args);
builder.WithCorrelationVector();
var app = builder.Build();
app.UseCorrelationVector();

Accessing the correlation vector

Take a dependency on IHttpContextAccessor and get the CV using the HttpContextExtensions.GetCorrelationVector method

var cv = accessor.HttpContext.GetCorrelationVector();

Configuration

Configure an instance of CorrelationVectorOptions to adjust the CV header

Requests and responses

  • On a request, the CorrelationVectorMiddleware retrieves the CV from the request header if present, otherwise it creates a new one
  • The CV is stored in HttpContext.Items under CorrelationVector key
  • Log the CV to follow traces of one application flow under multiple operations and across http requests

Integration with HttpClient

  • Pass the CorrelationVectorHandler to the IHttpClientBuilder to manage CVs across requests
  • On each HttpClient request, the CV is added to the configured header
  • After receiving the response, the CorrelationVectorHandler will receive and parse any existing CV from the headers and reapply it to the HttpContext.Items

Client IP extraction

IPExtractingMiddleware figures out the IP of the client, being able to handle reverse proxying through X-Forwarded-For header as well as CloudFlare specific CF-Connecting-IP header

Integration into WebApplication

var builder = WebApplication.CreateSlimBuilder(args);
builder.WithIPExtraction();
var app = builder.Build();
app.UseIPExtraction();

Accessing the client IP

Take a dependency on IHttpContextAccessor and get the CV using the HttpContextExtensions.GetCorrelationVector method

var cv = accessor.HttpContext.GetClientIP();

Better configuration binding support

Integration into WebApplication

var builder = WebApplication.CreateSlimBuilder(args);
builder.ConfigureExtended<CustomOptions>();

public class CustomService 
{
    public CustomService (IOptions<CustomOptions> options)
    {
    }
}

Customizing configuration key

[OptionsName(Name = "CustomKey")]
public class CustomOptions
{

}

Mockable HttpClient

Integration into WebApplication

var builder = WebApplication.CreateSlimBuilder(args);
builder.RegisterHttpClient<CustomService>()
    .WithTimeout(TimeSpan.FromSeconds(5))
    .WithCorrelationVector()
    .CreateBuilder();

public class CustomService
{
    public CustomService (IHttpClient<CustomService> client)
    {
    }
}

Base64 to X509Certificate2 converter for options

Use the Base64ToCertificateConverter to retrieve your SSL certificate from configuration and bind it to options, to allow for dynamic loading of certificates

Use Base64ToCertificateConverter on your X509Certificate2 property

public class ServerOptions
{
    [JsonConverter(typeof(Base64ToCertificateConverter))]
    public X509Certificate2 Certificate { get; set; } = default!;
}

About

.NET library extending functionality for web applications. Source generators for .Net.Sdk that implement the MVC functionality for Asp with NativeAOT support.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages