Inputs – Minimal API

An endpoint rarely has no parameter (no input value). Minimal APIs, like MVC, support a wide variety of binding sources. A binding source represents the conversion from the HTTP request into a strongly typed C# object, inputted as a parameter. Most of the parameter binding happens implicitly, but in case you need to bind a parameter explicitly, here are the supported binding sources:

SourceAttributeDescription
Route[FromRoute]Binds the route value that matches the name of the parameter.
Query[FromQuery]Binds the query string value that matches the name of the parameter.
Header[FromHeader]Binds the HTTP header value that matches the name of the parameter.
Body[FromBody]Binds the JSON body of the request to the parameter’s type.
Form[FromForm]Binds the form value that matches the name of the parameter.
Services[FromServices]Inject the service from the ASP.NET Core dependency container.
Custom[AsParameters]Binds the form values to a type. The matches happen between the form keys and the properties’ names.

 Table 5.2: supported binding sources

Next is a demo where we implicitly bind the id parameter from the route (highlighted code) to a parameter in the delegate:

app.MapGet(
    “minimal-endpoint-input-route-implicit/{id}”,
    (int id) => $”The id was {id}.”
);

In most cases, the bindings work implicitly. However, you can explicitly bind the delegate’s parameters like this:

app.MapGet(
    “minimal-endpoint-input-route-explicit/{id}”,
    ([FromRoute] int id) => $”The id was {id}.”
);

We can also implicitly inject dependencies into our delegates and even mix that with a route parameter like this:

app.MapGet(
    “minimal-endpoint-input-service/{value}”,
    (string value, SomeInternalService service)
        => service.Respond(value)
);
public class SomeInternalService {
    public string Respond(string value)
        => $”The value was {value}”;
}

Following this pattern opens endless possibilities to input data into our endpoints.

If you are unfamiliar with Dependency Injection (DI), we explore DI more in-depth in Chapter 8, Dependency Injection. Meanwhile, remember that we can bind objects to parameters, whether they are a DTO or a service.

On top of that, ASP.NET Core provides us with a few special types, which we explore next.

Special types

We can inject the following objects into our delegates as parameters, and ASP.NET Core manages them for us:

ClassDescription
HttpContextThe HttpContext encompasses all the current HTTP request and response details. The HttpContext exposes all the other special types we are exploring here, so if you need more than one, you can inject the HttpContext directly to reduce the number of parameters.
HttpRequestWe can use the HttpRequest to do basic HTTP operations on the current request, like query the parameters manually and bypass the ASP.NET Core data-binding mechanism. Same as the HttpContext.Request property.
HttpResponseLike the HttpRequest , we can leverage the HttpResponse object to execute manual operations on the HTTP response, like writing directly to the response stream, managing HTTP headers manually, etc. Same as the HttpContext.Response property.
CancellationTokenPassing a cancellation token to an asynchronous operation is a recommended practice. In this case, it allows canceling the operation when the request is canceled. Same as the HttpContext.RequestAborted property.
ClaimsPrincipalTo access the current user, we can inject a ClaimsPrincipal instance. Same as the HttpContext.User property.

 Tabel 5.3: special HTTP types

Here’s an example where two endpoints write to the response stream, one using the HttpContext and the other the HttpResponse object:

app.MapGet(
    “minimal-endpoint-input-HttpContext/”,
    (HttpContext context)
        => context.Response.WriteAsync(“HttpContext!”)
);
app.MapGet(
    “minimal-endpoint-input-HttpResponse/”,
    (HttpResponse response)
        => response.WriteAsync(“HttpResponse!”)
);

We can treat those special types like any other bindings and seamlessly integrate them with other types, such as route values and services.We cover one last piece of data-binding next.

You may also like