过程,controller下的路由是怎么来的。最后落到了,DefaultApplicationModelProvider下面的CreateActionModel,
参考来自此,(78条消息) .netcore入门13:aspnetcore源码之如何在程序启动时将Controller里的Action自动扫描封装成Endpoint_jackletter的博客-CSDN博客
一、探索目的说明
我们知道在程序启动时,程序就会扫描所有相关程序集中Controller的Action,然后将他们封装成一个个的Endpoint交给“路由”模块去管理,这样在http请求到来时“路由”模块才能寻找到正确的Endpoint,进而找到Action并调用执行。这里我们正是要探索“程序在启动时如何扫描Action并封装成Endpoint”的。
————————————————
版权声明:本文为CSDN博主「jackletter」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010476739/article/details/104545284
正常的Controller的Action怎么变成Endpoint的。
services.AddControllers()--->ActionDescriptor
MvcCoreServiceCollectionExtensions.cs
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApplicationModelProvider, DefaultApplicationModelProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IApplicationModelProvider, ApiBehaviorApplicationModelProvider>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IActionDescriptorProvider, ControllerActionDescriptorProvider>());
ControllerActionDescriptorProvider->ControllerActionDescriptorBuilder
endpoints.MapControllers()--->
EndPoint
热拔插系统,会通知修改,在change之后,会upEndPoint
我的问题是怎么修改 EndPoint 的路由。
重写DefaultApplicationModelProvider,不太现实。在bing里面翻了半天。突然看到
https://www.vb-net.com/AspNet-DocAndSamples-2017/aspnetcore/mvc/controllers/application-model.htm
下面一个例子
Sample: Custom Routing Convention
You can use an IApplicationModelConvention
to customize how routing works. For example, the following convention will incorporate Controllers’ namespaces into their routes, replacing .
in the namespace with /
in the route:
[!code-csharpMain]
1: using Microsoft.AspNetCore.Mvc.ApplicationModels;
2: using System.Linq;
3:
4: namespace AppModelSample.Conventions
5: {
6: public class NamespaceRoutingConvention : IApplicationModelConvention
7: {
8: public void Apply(ApplicationModel application)
9: {
10: foreach (var controller in application.Controllers)
11: {
12: var hasAttributeRouteModels = controller.Selectors
13: .Any(selector => selector.AttributeRouteModel != null);
14:
15: if (!hasAttributeRouteModels
16: && controller.ControllerName.Contains("Namespace")) // affect one controller in this sample
17: {
18: // Replace the . in the namespace with a / to create the attribute route
19: // Ex: MySite.Admin namespace will correspond to MySite/Admin attribute route
20: // Then attach [controller], [action] and optional {id?} token.
21: // [Controller] and [action] is replaced with the controller and action
22: // name to generate the final template
23: controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel()
24: {
25: Template = controller.ControllerType.Namespace.Replace('.', '/') + "/[controller]/[action]/{id?}"
26: };
27: }
28: }
29:
30: // You can continue to put attribute route templates for the controller actions depending on the way you want them to behave
31: }
32: }
33: }
The convention is added as an option in Startup.
[!code-csharpMain]
1: using AppModelSample.Conventions;
2: using Microsoft.AspNetCore.Builder;
3: using Microsoft.AspNetCore.Hosting;
4: using Microsoft.Extensions.Configuration;
5: using Microsoft.Extensions.DependencyInjection;
6: using Microsoft.Extensions.Logging;
7:
8: namespace AppModelSample
9: {
10: public class Startup
11: {
12: public Startup(IHostingEnvironment env)
13: {
14: var builder = new ConfigurationBuilder()
15: .SetBasePath(env.ContentRootPath)
16: .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
17: .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
18: .AddEnvironmentVariables();
19: Configuration = builder.Build();
20: }
21:
22: public IConfigurationRoot Configuration { get; }
23:
24: // This method gets called by the runtime. Use this method to add services to the container.
25: #region ConfigureServices
26: public void ConfigureServices(IServiceCollection services)
27: {
28: services.AddMvc(options =>
29: {
30: options.Conventions.Add(new ApplicationDescription("My Application Description"));
31: options.Conventions.Add(new NamespaceRoutingConvention());
32: //options.Conventions.Add(new IdsMustBeInRouteParameterModelConvention());
33: });
34: }
35: #endregion
36:
37: // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
38: public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
39: {
40: loggerFactory.AddConsole(Configuration.GetSection("Logging"));
41: loggerFactory.AddDebug();
42:
43: if (env.IsDevelopment())
44: {
45: app.UseDeveloperExceptionPage();
46: app.UseBrowserLink();
47: }
48: else
49: {
50: app.UseExceptionHandler("/Home/Error");
51: }
52:
53: app.UseStaticFiles();
54:
55: app.UseMvc(routes =>
56: {
57: routes.MapRoute(
58: name: "default",
59: template: "{controller=Home}/{action=Index}/{id?}");
60: });
61: }
62: }
63: }
[!TIP] You can add conventions to your (xref:)middleware by accessing
MvcOptions
usingservices.Configure<MvcOptions>(c => c.Conventions.Add(YOURCONVENTION));
This sample applies this convention to routes that are not using attribute routing where the controller has “Namespace” in its name. The following controller demonstrates this convention:
[!code-csharpMain]
ControllerActionDescriptorBuilder->ApplicationModelFactory->ApplicationModelConventions->IApplicationModelProvider
解决了我的问题。
根据dll的名称来 改变路由。
代码的确是很复杂。
标签:--,app,庆军,热拔,controller,action,services,using,public From: https://www.cnblogs.com/forhell/p/16907566.html