Sebastiaan Dammann

Blogging, coding, 3D printing and reviews

ASP.NET Core 3.0 Endpoint routing naming and link generation

ASP.NET Core 3.0 introduced endpoint routing as a first class citizen. You can easily create endpoints and map them to your own RequestDelegate that will process the request. It is however not apparent how you can name your endpoints so you can reference them elsewhere, like in routing and link generation.

I upgraded my IFS project to ASP.NET Core 3.0 with endpoint routing. In the project I use a handler that will take the HTTP upload request and process it.

I mapped the endpoint like this:

app.UseEndpoints(endpoints =>
{
    endpoints.Map("upload/handler/{fileIdentifier}", UploadHandler.ExecuteAsync)
	// [...]
    endpoints.MapControllers();
    endpoints.MapDefaultControllerRoute();
});

However, I couldn’t reference this endpoint from a form or any other place where I needed link generation:

<form asp-route="????" />

None of the overloads of the endpoints object support naming, nor does the IEndpointConventionBuilder that is returned from the Map call. I downloaded the MVC source code, and explored how any routing attributes where added to the endpoint mapping.

To name your endpoint, you need to attach metadata to it using the IEndpointConventionBuilder. You need EndpointNameMetadata and RouteNameMetadata which both accept a name as string.

You can use it like this:

endpoints.Map("upload/handler/{fileIdentifier}", UploadHandler.ExecuteAsync)
         .WithMetadata(
			new EndpointNameMetadata("UploadHandler"),
			new RouteNameMetadata("UploadHandler")
	     )

The RouteNameMetadata metadata is used when creating routes and EndpointNameMetadata when using the GetByName method of the LinkGenerator class. You can create an extension method for convenience:

public static IEndpointConventionBuilder WithName(this IEndpointConventionBuilder endpointBuilder,string endpointName)
{
    return endpointBuilder.WithMetadata(
                new EndpointNameMetadata(endpointName),
                new RouteNameMetadata(endpointName)
           );
}

Which allows you to:

endpoints.Map("route/to/handler/{routeArgument}", MyHandler.ExecuteAsync)
         .WithName("MyHandler")

And then:

<a asp-route="MyHandler"></a> <!-- or: -->
<form asp-route="MyHandler"></form>

I hope this helps anyone who runs into the same issue. Happy coding!

What are your thoughts?