RouteContext

  我们知道,Startup.cs 中的 Configure(IApplicationBuilder app) 中,我们使用 app.UseMvc()在 UseMVC() 代码执行的过程中,它可以接收一个 Action 形式的委托,我们使用这个委托可以进行自定义路由的配置,默认情况下,我们一般会如下进行配置:

  app.UseMvc(routes =>

  {

  routes.MapRoute(

  name: "default",

  template: "{controller=Home}/{action=Index}/{id?}");

  });

  或者是你使用默认的 app.UseMvcWithDefaultRoute(),这个扩展方法在内部已经帮你做了上述代码的内容。

  那我们今天就从这个 Route 的配置开始看起吧。

  RouteContext 如何初始化?

  在 IRouteBuilder 通过配置 IRouteBuilder,IRouteBuilder 在 Build() 之后会得到 Router 会得到 IRouter。

  public static IApplicationBuilder UseMvc(

  this IApplicationBuilder app,

  Action configureRoutes)

  {

  // ......

  var routes = new RouteBuilder(app)

  {

  DefaultHandler = app.ApplicationServices.GetRequiredService(),

  };

  configureRoutes(routes);

  routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));

  return app.UseRouter(routes.Build());

  }

  上面的代码有两个地方需要注意的。

  第一个地方是 DefaultHandler,可以看到默认配置下,MVC 程序从 DI 中获取 MvcRouteHandler 路由处理程序来作为路由的默认处理程序。

  第二个地方是 AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices)

  ,那么这个地方是干嘛的呢?

  CreateAttributeMegaRoute 它返回了一个 IRouter ,主要是用来处理带 RouteAttribute 标记的 Action,我们来看一下这个方法:

  public static IRouter CreateAttributeMegaRoute(IServiceProvider services)

  {

  return new AttributeRoute(

  services.GetRequiredService(),

  services,

  actions =>

  {

  var handler = services.GetRequiredService();

  handler.Actions = actions;

  return handler;

  });

  }

  在方法内部,new 了一个 AttributeRoute 返回了回去,大家可以看到有一个参数 actions,它使用的是 MvcAttributeRouteHandler 这个处理程序,说明在实际调用过程中使用的是 MvcAttributeRouteHandler 进行的路由处理。

  OK,我们总结一下关于 MVC 自己的几个路由处理程序,还是用一个图比较容易看的清楚,幸运的是,MVC 一共就这3个路由处理程序,我们已经全部接触到了。

  MVC 框架针对于 IRouter 接口的实现有以下三个:

  提前告诉你,最左边绿色的那个 AttributeRoute 其实只是一个包装,在内部也是通过 MvcAttributeRouteHandler 或者 MvcRouteHandler 进行的处理。那么,现在关于路由的处理程序只剩下了两个,他们分别是:

  默认处理程序: MvcRouteHandler,用来处理约定的 Action。

  注解处理程序: MvcAttributeRouteHandler ,用来处理注解(Attribute)路由。

  细心的同学可能注意到了, MvcAttributeRouteHandler 比 MvcRouteHandler 多了一个 Actions : ActionDescriptor[]属性。

  我们再看一下这两个处理程序的 RouteAsync 方法,这个方法是路由组件的入口方法,我们通过一个对比工具来看一下两者之间的差距。

  图片看不清楚可以新标签打开

  可以看到,这两个 RouteAsync 主要有两处差距,第一处就是 SelectBestCandidate 这个函数第二个参数

  ActionDescriptor SelectBestCandidate(RouteContext context, IReadOnlyList candidates)

  MvcRouteHandler:

  在这个流程中,显示调用了 IActionSelect 接口中的 SelectCandidates() 用来找到所有符合条件的候选 Action,然后调用了 SelectBestCandidate 找出最佳的一个。

  程序走到这里,这里会有两个重点的地方,或者叫有疑问的地方?

  1、 程序集中定义的 Action 是怎么找到的?

  要想找到程序定义的所有 Action,那么首先需要找到 Controller,在上一篇文章中我们已经知道了有一个 MVC 程序用来管理 AssemblyPart 的东西叫 ApplicationPartManager ,它的里面存储了所有 MVC 框架在启动的时候加载的所有程序集,那么我们可以从这个程序集中找到需要的 Controller。下面这个流程图显示了查找Controller 的流程:

  GetControllerTypes 返回的是一个 IEnumerable 的集合,有了 Controller 之后,MVC 框架使用了一个对象来包装 Controller,因为在后续的流程中,除了需要 Controller 之外还需要其他的一些东西,比如 Filter, ApiExplorer 等。

  ApplicationModel

  ApplicationModel 就是MVC框架用来包装 Controller,Filter , ApiExplorer 等的一个Model 对象,我们来看一下它的定义:

  public class ApplicationModel : IPropertyModel, IFilterModel, IApiExplorerModel

  {

  public ApplicationModel()

  {

  ApiExplorer = new ApiExplorerModel();

  Controllers = new List();

  Filters = new List();

  Properties = new Dictionary();

  }

  public ApiExplorerModel ApiExplorer { get; set; }

  public IList Controllers { get; private set; }

  public IList Filters { get; private set; }

  public IDictionary Properties { get; }

  }

  ApplicationModel 里面关于 Controller 的包装是一个 IList,看一下 ControllerModel 的定义:

  public class ControllerModel : ICommonModel, IFilterModel, IApiExplorerModel

  {

  //......

  public IList Actions { get; }

  public ApiExplorerModel ApiExplorer { get; set; }

  public ApplicationModel Application { get; set; }

  public IReadOnlyList

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Module not found: Error: Can't resolve 'redux-thunk' in 'C:\Users\烟火阑珊倚人间\bookstore-admin\src' ERROR in ./src/App.js 51:42-50 export 'Redirect' (imported as 'Redirect') was not found in 'react-router-dom' (possible exports: AbortedDeferredError, Await, BrowserRouter, Form, HashRouter, Link, MemoryRouter, NavLink, Navigate, NavigationType, Outlet, Route, Router, RouterProvider, Routes, ScrollRestoration, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, UNSAFE_useRouteId, UNSAFE_useScrollRestoration, createBrowserRouter, createHashRouter, createMemoryRouter, createPath, createRoutesFromChildren, createRoutesFromElements, createSearchParams, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, renderMatches, resolvePath, unstable_HistoryRouter, unstable_useBlocker, unstable_usePrompt, useActionData, useAsyncError, useAsyncValue, useBeforeUnload, useFetcher, useFetchers, useFormAction, useHref, useInRouterContext, useLinkClickHandler, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes, useSearchParams, useSubmit) ERROR in ./src/App.js 66:41-47 export 'Switch' (imported as 'Switch') was not found in 'react-router-dom' (possible exports: AbortedDeferredError, Await, BrowserRouter, Form, HashRouter, Link, MemoryRouter, NavLink, Navigate, NavigationType, Outlet, Route, Router, RouterProvider, Routes, ScrollRestoration, UNSAFE_DataRouterContext, UNSAFE_DataRouterStateContext, UNSAFE_LocationContext, UNSAFE_NavigationContext, UNSAFE_RouteContext, UNSAFE_useRouteId, UNSAFE_useScrollRestoration, createBrowserRouter, createHashRouter, createMemoryRouter, createPath, createRoutesFromChildren, createRoutesFromElements, createSearchParams, defer, generatePath, isRouteErrorResponse, json, matchPath, matchRoutes, parsePath, redirect, renderMatches, resolvePath, unstable_HistoryRouter, unstable_useBlocker, unstable_usePrompt, useActionData, useAsyncError, useAsyncValue, useBeforeUnload, useFetcher, useFetchers, useFormAction, useHref, useInRouterContext, useLinkClickHandler, useLoaderData, useLocation, useMatch, useMatches, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRouteLoaderData, useRoutes, useSearchParams, useSubmit)
07-25

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值