Configure the global routing prefix in ASP. NET Core MVC and coremvc
Reference page:
Http://www.yuanjiaocheng.net/ASPNET-CORE/core-setup-entityframework.html
Http://www.yuanjiaocheng.net/ASPNET-CORE/core-dbcontext.html
Http://www.yuanjiaocheng.net/ASPNET-CORE/core-razor-layout.html
Http://www.yuanjiaocheng.net/ASPNET-CORE/core-view-start.html
Http://www.yuanjiaocheng.net/ASPNET-CORE/core-import-view.html
Preface
Hello everyone, today we will introduce a new feature of ASP. NET Core MVC and add a unified prefix to global routes. Strictly speaking, it is not a new feature, but a unique feature of Core MVC.
Application background
I don't know if you have encountered such a scenario when using Web Api applications, that is, all interfaces start with/api, that is, our api request address is like this:
http://www.example.com/api/order/333
Or such a requirement
http://www.example.com/api/v2/order/333
In the past, if we wanted to implement this kind of requirement, we could add[Route("/api/order")]
With this feature, the MVC Framework will scan your route table to match/api/order
Such a request.
However, the second requirement with a version number is as follows:[Route("/api/v1/order")]
Now we need to upgrade to v2 with more than interfaces, which requires one modification, and may be forced.
Now there is a simpler and more elegant way to do this. You can add a global prefix routing tag in a unified manner. Let's take a look at it.
IApplicationModelConvention Interface
First, we need to useIApplicationModelConvention
This interface is located inMicrosoft.AspNetCore.Mvc.ApplicationModels
In the namespace, let's take a look at the interface definition.
public interface IApplicationModelConvention{ void Apply(ApplicationModel application);}
We know that the MVC framework has some common things, so this interface is mainly used to customize some of the MVC conventions. We can specifyApplicationModel
Object To add or modify some conventions. You can see that the interface providesApply
This method hasApplicationModel
Object, we can use this object to modify what we need. The MVC framework itself injects this interface into Services at startup, so we only need to implement this interface, then you can configure it with a little bit.
Let's take a look.ApplicationModel
What does this object have:
public class ApplicationModel : IPropertyModel, IFilterModel, IApiExplorerModel{ public ApiExplorerModel ApiExplorer { get; set; } public IList<ControllerModel> Controllers { get; } public IList<IFilterMetadata> Filters { get; } public IDictionary<object, object> Properties { get; }}
You can see thatApiExplorer
,Controllers
,Filters
,Properties
.
- Apicyclermodel: Mainly used to configure the default MVC Api Explorer, including the Api description, group information, and visibility.
- ControllerModel: it is mainly related to the default Comtroller conventions. There are more things in it, so we will not introduce them one by one. We will wait for a while to configure one thing in it.
- IFilterMetadata: Empty interface, mainly used for marking.
Another thing we need to tell you is,You can see that the Controllers attribute above isIList<ControllerModel>
That is to say, this list records information about all controllers in your program. You can set a certain part or Controller through traversal, the Actions information in the Controller can be set in this way. We can use this feature to flexibly modify the MVC framework.Is it cool.
Next, we will use this feature to implement our theme today. Thank you for your thumbs up ~ :)
Add unified global route prefix
There is not so much nonsense. You can directly add the code. All you have to say is in the Code:
// Define a class RouteConvention to implement the invoke interface public class RouteConvention: Rule {private readonly AttributeRouteModel _ centralPrefix; public RouteConvention (condition) {_ centralPrefix = new AttributeRouteModel (condition );} // Apply method of the interface public void Apply (ApplicationModel application) {// traverse all controllers foreach (var Controller in application. Controllers) {// Controller var matchedSelectors = controller. Selectors. Where (x => x. AttributeRouteModel! = Null ). toList (); if (matchedSelectors. any () {foreach (var selectorModel in matchedSelectors) {// Add a route prefix selectorModel to the current route. attributeRouteModel = AttributeRouteModel. combineAttributeRouteModel (_ centralPrefix, selectorModel. attributeRouteModel); }}// Controller var unmatchedSelectors = controller without RouteAttribute. selectors. where (x => x. attributeRouteModel = null ). toList (); if (unmatchedSelectors. any () {foreach (var selectorModel in unmatchedSelectors) {// Add a route prefix selectorModel. attributeRouteModel = _ centralPrefix ;}}}}}
Then, we can start to use the class we have defined.
Public static class MvcOptionsExtensions {public static void UseCentralRoutePrefix (this MvcOptions opts, IRouteTemplateProvider routeAttribute) {// Add RouteConvention opts for implementing IApplicationModelConvention. conventions. insert (0, new RouteConvention (routeAttribute ));}}
Finally, add the above Extension Method in the Startup. cs file.
Public class Startup {public Startup (IHostingEnvironment env ){//...} public void ConfigureServices (IServiceCollection services ){//... services. addMvc (opt => {// The route parameter is still valid here, for example, add a version number opt. useCentralRoutePrefix (new RouteAttribute ("api/v {version}");} public void Configure (IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory ){//... app. useMvc ();}}
Where,opt.UseCentralRoutePrefix
This is the extension method defined above. Here the routing parameters can still be used, so for example, you can specify a version number for your interface. In this way, the RoteAttribute of all your controllers will be added with this prefix, which perfectly solves the needs of the first version number. They look like this:
[Route ("order")] public class OrderController: Controller {// Route address: /api/v {version}/order/details/{id} [Route ("details/{id}")] public string GetById (int id, int version) {// the version number can be received, and the returned version and id return $ "other resource: {id}, version: {version}" ;}} public class ItemController: controller {// Route address:/api/v {version}/item/{id} [Route ("item/{id}")] public string GetById (int id, int version) {// the version number can be received above. The returned version and id return $ "item: {id}, version: {version }";}}
Summary
I hope you can understand and use the above in bold Chinese. This example is only a small scenario in actual needs. There will be various normal or abnormal requirements in specific projects, we need to think more about a function. In fact, the MVC framework still has many things to learn, including its design ideas and scalability. If you are interested in ASP. NET Core, please pay attention to me. I will share some of my learning achievements on a regular basis in my blog.
Thank you for your support. If you think this article is helpful to you, thank you for your [recommendation]. Good night ~.
Address: http://www.cnblogs.com/savorboard/p/dontnet-IApplicationModelConvention.html
Author's blog: Savorboard
You are welcome to repost it. Please provide the source and link clearly