Search code examples
c#asp.net-web-apiowinowin-middleware

Get the Route Template from IOwinContext


I am looking to get the route template from a request. I am using OwinMiddleware and am overriding the Invoke method accepting the IOwinContext.

public override async Task Invoke(IOwinContext context)
{
    ...
}

Given the Request URL: http://api.mycatservice.com/Cats/1234

I want to get "Cats/{CatId}"

I have unsuccessfully tried converting it using the following approachs:

HttpRequestMessage msg = new HttpRequestMessage(new HttpMethod(context.Request.Method), context.Request.Uri);

HttpContextBase httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

For reference:

Here is a post about how to do this using HttpRequestMessage which I have successfully implemented for another project


Solution

  • I had the same problem, this seems to work. A bit by magic, but so far so good:

    public class RouteTemplateMiddleware : OwinMiddleware
    {
        private const string HttpRouteDataKey = "MS_SubRoutes";
        private readonly HttpRouteCollection _routes;
    
        public RouteTemplateMiddleware(OwinMiddleware next, HttpRouteCollection routes) : base(next)
        {
            _routes = routes;
        }
    
        public override async Task Invoke(IOwinContext context)
        {
            var routeData = _routes.GetRouteData(new HttpRequestMessage(new HttpMethod(context.Request.Method), context.Request.Uri));
            var routeValues = routeData?.Values as System.Web.Http.Routing.HttpRouteValueDictionary;
    
            var route = routeValues?[HttpRouteDataKey] as System.Web.Http.Routing.IHttpRouteData[];
            var routeTemplate = route?[0].Route.RouteTemplate;
    
            // ... do something the route template
    
            await Next.Invoke(context);
        }
    }
    

    Register the middleware like so:

    public void Configuration(IAppBuilder app)
    {
        _httpConfiguration = new HttpConfiguration();
        _httpConfiguration.MapHttpAttributeRoutes();
        ...
    
        app.Use<RouteTemplateMiddleware>(_httpConfiguration.Routes);
        ...
    }