Introducing Strathweb.TypedRouting for ASP.NET MVC Core

Datetime:2016-08-23 04:40:22          Topic: ASP.NET MVC           Share

One of the side projects I created for Web API a while ago was Strathweb.TypeRouting – a little library built on top of the attribute routing extensibility points, that allowed you to declare Web API routes centrally, in a strongly typed way (as opposed to the built in, anonymous object approach).

Then, some time ago, Iblogged about how you would achieve the same thing in ASP.NET Core. A bunch of things have changed since then – the original post was written against beta6 of the framework I believe.

Last week, I set up the code on Github , migrated everything to RC2 and released on NuGet for everyone to use.


So in short, Strathweb.TypedRouting.AspNetCore is a next incarnation of the Strathweb.TypeRouting library from the ASP.NET Web API world, which enables strongly typed routing in ASP.NET Core MVC projects.

nugetinstallStrathweb.TypedRouting.AspNetCore -pre


In your Startup class, after adding MVC, call opt.EnableTypedRouting(); and then configure your routes:

        services.Configure<MvcOptions>(opt =>
            opt.Get("homepage", c => c.Action<HomeController>(x => x.Index()));
            opt.Get("aboutpage/{name}", c => c.Action<HomeController>(x => x.About(Param<string>.Any)));
            opt.Post("sendcontact", c => c.Action<HomeController>(x => x.Contact()));

This creates:

  • a GET route to /homepage
  • a GET route to /aboutpage/{name}
  • a POST route to /sendcontact

All of which go against the relevant methods on our HomeController .

Link generation

Since the API is fluent, you can also give the routes names so that you can use them with i.e. link generation.

opt.Get("api/values/{id}", c => c.Action<ValuesController>(x => x.Get(Param<int>.Any))).WithName("GetValueById");

Now you can use it with IUrlHelper (it’s a Url property on every controller):

var link = Url.Link("GetValueById", new { id = 1 });

IUrlHelper can also be obtained from HttpContext , anywhere in the pipeline (i.e. in a filter):

var services = context.HttpContext.RequestServices;
var urlHelper = services.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
var link = urlHelper.Link("GetValueById", new { id = 1 });

Finally, you can also use this link generation technique with the built-in action results, such as for example CreatedAtRouteResult :

        public IActionResultPost([FromBody]string value)
            var result = CreatedAtRoute("GetValueById", new { id = 1 }, "foo");
            return result;

Route constraints

The library supports two ways of specifying route constraints:

  • inline in the template
  • via fluent API

The inline constraints are the same as you can use with attribute routing. For example:

opt.Get("api/other/{id:int}", c => c.Action<OtherController>(x => x.Action2(Param<int>.Any)));

You can also specify constraints via the fluent API, by chaining IActionConstraintMetadata implementations. Consider the following sample constraint class:

    public class ManadatoryHeaderConstraint : IActionConstraint, IActionConstraintMetadata
        private string _header;
        public ManadatoryHeaderConstraint(string header)
            _header = header;
        public int Order => 0;
        public bool Accept(ActionConstraintContextcontext)
            // only allow route to be hit if the predefined header is present
            if (context.RouteContext.HttpContext.Request.Headers.ContainsKey(_header))
                return true;
            return false;

You can now use this class in the route declaration:

opt.Get("api/other", c => c.Action<OtherController>(x => x.Action1())).WithConstraints(new ManadatoryHeaderConstraint("CustomHeader"));


If you have any ideas, suggestions or want to help – please visit Github . Thanks!

About List