RooSoft
RooSoft

Reputation: 1501

ASP.NET Core Middleware and URL Parsing

Trying to add special endpoints to an ASP.NET Core MVC through a middleware.

In a app.UseWhen, I need to parse the request URL. In a Controller context, MVC does a great job extracting userId using the following template:

GET http://contoso.com/users/{userId}/addresses

How could this be cleanly done in a middleware where MVC Controller constructs aren't setup?

Bonus points if the answer helps figuring out if the address conforms to this pattern in the first place.

All I have on hand is a DefaultHttpContext.

Upvotes: 3

Views: 8860

Answers (3)

RooSoft
RooSoft

Reputation: 1501

Solution based on Mark Vincze's blog

This method used to extract the the user id and work with it...

    private static void AddAddressesRoute(IApplicationBuilder app, RouteBuilder builder)
    {
        builder.MapVerb(
            HttpMethod.Get.Method,
            "users/{userId}/addresses",
            async context =>
            {
                var routeData = context.GetRouteData();
                var userId = routeData.Values["userId"];

                // userId available from here
            }
        );
    }

Should be initiated from an application builder extension method.

    public static IApplicationBuilder UseAddresses(
        this IApplicationBuilder app
    )
    {
        RouteBuilder builder = new RouteBuilder(app);

        AddAddressesRoute(app, builder);

        app.UseRouter(builder.Build());

        return app;
    }

Becomes a middleware that can be added to the Startup.Configure method just like this:

    app.UseAddresses()

It doesn't even interfere with MVC that still gets triggered if the route doesn't match.

Upvotes: 2

Culpepper
Culpepper

Reputation: 1111

You can access the HttpContext from middleware and parse out key-value pairs from the query string but you can not access the path parameters via key-value.

For example:

You make a GET to the following controller via http://contoso.com/api/users/5?zip=90210:

 // GET api/users/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
    return "value";
}

Custom Middleware:

public class MyCustomMiddleware
{
    public Task InvokeAsync(HttpContext context)
    {   
        // get full path from context request path
        var queryPath = context.Request.Path().ToString(); 
        // will return /api/users/5

        // get id from query string
        var queryStringId = context.Request.Query["zip"].ToString();
        // will return 90210
    }
}

There isn't any mapping from your Controller parameters to the HttpContext.

Upvotes: 1

Dmitry Pavlov
Dmitry Pavlov

Reputation: 28320

URL parsing comes to play in MVC pipeline, not in ASP.NET Core one.

You might want to consider MVC filters instead, which have access to routing context.

Upvotes: 0

Related Questions