Introducing Strathweb TypedRouting for ASP.NET MVC Core

Β· 477 words Β· 3 minutes to read

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, I blogged 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.

Installation πŸ”—

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.

nuget install Strathweb.TypedRouting.AspNetCore -pre

Setup πŸ”—

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

services.AddMvc();

services.Configure<MvcOptions>(opt =>  
{  
opt.EnableTypedRouting();  
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.

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 IActionResult Post([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(ActionConstraintContext context)  
{  
// 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"));  

Contribute πŸ”—

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

About


Hi! I'm Filip W., a cloud architect from ZΓΌrich πŸ‡¨πŸ‡­. I like Toronto Maple Leafs πŸ‡¨πŸ‡¦, Rancid and quantum computing. Oh, and I love the Lowlands 🏴󠁧󠁒󠁳󠁣󠁴󠁿.

You can find me on Github and on Mastodon.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP