Orchard对mvc路由重新做了包装,重写了asp.net的路由模块

一、路由模块类图
1、路由 Descriptor

RouteDescriptor是对常规mvc路由的包装类,它的Route属性就是在mvc注册路由中使用的RouteBase类型。在Orchard中注册路由,应该用这种方式
  1. newRouteDescriptor{
    Route=newRoute(
    "Admin/Blogs/Create",
    newRouteValueDictionary{
    {"area","Orchard.Blogs"},
    {"controller","BlogAdmin"},
    {"action","Create"}
    },
    newRouteValueDictionary(),
    newRouteValueDictionary{
    {"area","Orchard.Blogs"}
    },
    newMvcRouteHandler())
    }
 
2、路由实现
    Orchard的路由实现有2个类组成:HubRoute和ShellRoute类。它们都继承了System.Web.Routing.RouteBase类,要重新实现GetRouteData和GetVirtualPath方法
2.1、HubRoute类中的GetRouteData方法
  1. publicoverrideRouteDataGetRouteData(HttpContextBase httpContext)
    {
    var settings = _runningShellTable.Match(httpContext); if(settings ==null)
    returnnull;
    //这里获取1个ShellRoute的集合
    IList<RouteBase> routes;
    if(!_routesByShell.TryGetValue(settings.Name,out routes))
    {
    returnnull;
    } foreach(var route in routes)
    {
    RouteData routeData = route.GetRouteData(httpContext);//这里的route是ShellRoute类型
    if(routeData !=null)
    {
    return routeData;
    }
    } returnnull;
    }
HubRoute类只是1个route的分配器,它的GetRouteData方法只是从1个ShellRoute集合中获取匹配的 ShellRoute,而真正的获取RouteData 实例的是ShellRoute 类中的 GetRouteData方法
 
2.2、ShellRoute中的GetRouteData方法
  1. publicoverrideRouteDataGetRouteData(HttpContextBase httpContext)
    {
    // locate appropriate shell settings for request
    var settings = _runningShellTable.Match(httpContext); // only proceed if there was a match, and it was for this client
    if(settings ==null|| settings.Name!= _shellSettings.Name)
    returnnull; var effectiveHttpContext = httpContext;
    if(_urlPrefix !=null)
    effectiveHttpContext =newUrlPrefixAdjustedHttpContext(httpContext, _urlPrefix); var routeData = _route.GetRouteData(effectiveHttpContext);//这里获取的是真正的mvc RouteData
    if(routeData ==null)
    returnnull; // otherwise wrap handler and return it
    routeData.RouteHandler=newRouteHandler(_workContextAccessor, routeData.RouteHandler,SessionState);
    routeData.DataTokens["IWorkContextAccessor"]= _workContextAccessor; if(IsHttpRoute)
    {
    routeData.Values["IWorkContextAccessor"]= _workContextAccessor;// for WebApi
    } return routeData;
    }
3、路由注册
    Orchard的路由注册功能由2个接口定义:IRouteProvider、IRoutePublisher。Orchard提供默认的实现:DefaultRouteProvider和RoutePublisher类
3.1、DefaultRouteProvider类:
  1. publicclassDefaultRouteProvider:IRouteProvider
    {
    //GetRoutes方法中定义了你要使用的所有的路由信息.
    publicIEnumerable<RouteDescriptor>GetRoutes()
    {
    returnnew[]{
    newRouteDescriptor{
    Priority=-,
    Route=newRoute(
    "{controller}/{action}/{id}",
    newRouteValueDictionary{
    {"controller","home"},
    {"action","index"},
    {"id",""},
    },
    newRouteValueDictionary{
    {"controller",newHomeOrAccount()}
    },
    newMvcRouteHandler())
    }
    };
    } publicvoidGetRoutes(ICollection<RouteDescriptor> routes)
    {
    foreach(var routeDescriptor inGetRoutes())
    routes.Add(routeDescriptor);
    } }
3.2、RoutePublisher类:
  1.  public void Publish(IEnumerable<RouteDescriptor> routes)
    {
    var routesArray = routes
    .OrderByDescending(r => r.Priority)
    .ToArray(); // this is not called often, but is intended to surface problems before
    // the actual collection is modified
    var preloading = new RouteCollection();
    foreach (var routeDescriptor in routesArray)
    { // extract the WebApi route implementation
    var httpRouteDescriptor = routeDescriptor as HttpRouteDescriptor;
    if (httpRouteDescriptor != null)
    {
    var httpRouteCollection = new RouteCollection();
    httpRouteCollection.MapHttpRoute(httpRouteDescriptor.Name, httpRouteDescriptor.RouteTemplate, httpRouteDescriptor.Defaults, httpRouteDescriptor.Constraints);
    routeDescriptor.Route = httpRouteCollection.First();
    } preloading.Add(routeDescriptor.Name, routeDescriptor.Route);
    } using (_routeCollection.GetWriteLock())
    {
    // existing routes are removed while the collection is briefly inaccessable
    _routeCollection
    .OfType<HubRoute>()
    .ForEach(x => x.ReleaseShell(_shellSettings)); // new routes are added
    foreach (var routeDescriptor in routesArray)
    {
    // Loading session state information.
    var defaultSessionState = SessionStateBehavior.Default; ExtensionDescriptor extensionDescriptor = null;
    if (routeDescriptor.Route is Route)
    {
    object extensionId;
    var route = routeDescriptor.Route as Route;
    if (route.DataTokens != null && route.DataTokens.TryGetValue("area", out extensionId) ||
    route.Defaults != null && route.Defaults.TryGetValue("area", out extensionId))
    {
    extensionDescriptor = _extensionManager.GetExtension(extensionId.ToString());
    }
    }
    else if (routeDescriptor.Route is IRouteWithArea)
    {
    var route = routeDescriptor.Route as IRouteWithArea;
    extensionDescriptor = _extensionManager.GetExtension(route.Area);
    } if (extensionDescriptor != null)
    {
    // if session state is not define explicitly, use the one define for the extension
    if (routeDescriptor.SessionState == SessionStateBehavior.Default)
    {
    Enum.TryParse(extensionDescriptor.SessionState, true /*ignoreCase*/, out defaultSessionState);
    }
    } // Route-level setting overrides module-level setting (from manifest).
    var sessionStateBehavior = routeDescriptor.SessionState == SessionStateBehavior.Default ? defaultSessionState : routeDescriptor.SessionState; var shellRoute = new ShellRoute(routeDescriptor.Route, _shellSettings, _workContextAccessor, _runningShellTable)
    {
    IsHttpRoute = routeDescriptor is HttpRouteDescriptor,
    SessionState = sessionStateBehavior
    }; var area = extensionDescriptor == null ? "" : extensionDescriptor.Id; var matchedHubRoute = _routeCollection.FirstOrDefault(x =>
    {
    var hubRoute = x as HubRoute;
    if (hubRoute == null)
    {
    return false;
    } return routeDescriptor.Priority == hubRoute.Priority && hubRoute.Area.Equals(area, StringComparison.OrdinalIgnoreCase) && hubRoute.Name == routeDescriptor.Name;
    }) as HubRoute; if (matchedHubRoute == null)
    {
    matchedHubRoute = new HubRoute(routeDescriptor.Name, area, routeDescriptor.Priority, _runningShellTable); int index;
    for (index = ; index < _routeCollection.Count; index++)
    {
    var hubRoute = _routeCollection[index] as HubRoute;
    if (hubRoute == null)
    {
    continue;
    }
    if (hubRoute.Priority < matchedHubRoute.Priority)
    {
    break;
    }
    } _routeCollection.Insert(index, matchedHubRoute);
    } matchedHubRoute.Add(shellRoute, _shellSettings);
    }
    }
    }
Publish方法将路由注册到asp.net mvc 的路由系统中。
 
二、如何在Module开发中使用路由系统
    Orchard的功能都是通过Module实现的。那么在Module开发中如何使用 路由呢?我们以Orcahrd自己的 Orchard.Blogs Module为例,在Orchard中实现自己的路由其实很简单,只需要在自己的Module中创建1个实现IRouteProvider接口的类型即可。
  1.  public class Routes : IRouteProvider
    {
    private readonly IArchiveConstraint _archiveConstraint;
    private readonly IRsdConstraint _rsdConstraint; public Routes(
    IArchiveConstraint archiveConstraint,
    IRsdConstraint rsdConstraint)
    {
    _archiveConstraint = archiveConstraint;
    _rsdConstraint = rsdConstraint;
    } public void GetRoutes(ICollection<RouteDescriptor> routes)
    {
    foreach (var routeDescriptor in GetRoutes())
    routes.Add(routeDescriptor);
    } public IEnumerable<RouteDescriptor> GetRoutes()
    {
    return new[] {
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/Create",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogAdmin"},
    {"action", "Create"}
    },
    new RouteValueDictionary(),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}/Edit",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogAdmin"},
    {"action", "Edit"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}/Remove",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogAdmin"},
    {"action", "Remove"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogAdmin"},
    {"action", "Item"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}/Posts/Create",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogPostAdmin"},
    {"action", "Create"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}/Posts/{postId}/Edit",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogPostAdmin"},
    {"action", "Edit"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}/Posts/{postId}/Delete",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogPostAdmin"},
    {"action", "Delete"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}/Posts/{postId}/Publish",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogPostAdmin"},
    {"action", "Publish"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs/{blogId}/Posts/{postId}/Unpublish",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogPostAdmin"},
    {"action", "Unpublish"}
    },
    new RouteValueDictionary (),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Admin/Blogs",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogAdmin"},
    {"action", "List"}
    },
    new RouteValueDictionary(),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "Blogs",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "Blog"},
    {"action", "List"}
    },
    new RouteValueDictionary(),
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Route = new Route(
    "{*path}",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "BlogPost"},
    {"action", "ListByArchive"}
    },
    new RouteValueDictionary {
    {"path", _archiveConstraint},
    },
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    },
    new RouteDescriptor {
    Priority = ,
    Route = new Route(
    "{*path}",
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"},
    {"controller", "RemoteBlogPublishing"},
    {"action", "Rsd"}
    },
    new RouteValueDictionary {
    {"path", _rsdConstraint}
    },
    new RouteValueDictionary {
    {"area", "Orchard.Blogs"}
    },
    new MvcRouteHandler())
    }
    };
    }
    }
三、Orchard路由系统如何工作的。
1、将自定义路由注册到asp.net mvc路由系统中
        这个工作是在创建和激活shell的时候,调用 DefaultOrchardShell类的Activate方法时进行的
  1. publicvoidActivate()
    {
    var allRoutes =newList<RouteDescriptor>();
    allRoutes.AddRange(_routeProviders.SelectMany(provider => provider.GetRoutes()));
    allRoutes.AddRange(_httpRouteProviders.SelectMany(provider => provider.GetRoutes())); _routePublisher.Publish(allRoutes);//这里就是注册路由
    _modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders())); using (var events = _eventsFactory())
    {
    events.Value.Activated();
    } _sweepGenerator.Activate();
    }
2、路由的使用:像mvc路由一样使用自定义路由。
 

Orchard学习 02、orchard 路由的更多相关文章

  1. Orchard 学习-安装Orchard

    前段时间使用一个ABP的框架进行了一个简单CMS开发.但感觉自己开发CMS不够灵活和通用,所以还是学习一下Orchard.学习的第一步,阅读官方的文档.由于是英文,所以我对其进行了翻译和记录,方便自己 ...

  2. Orchard学习笔记

    1.下载Orchard sourcrs资源文件,同时也可以去百度下载中文包 资源地址(https://github.com/OrchardCMS/Orchard/releases/download/1 ...

  3. 200. Orchard学习 目录

    201. Orchard学习 一.基础 210. Orchard学习 二.启动 211. Orchard学习 二 1.Application_Start 212. Orchard学习 二 2.Manu ...

  4. Orchard学习系列-----如何运行的

    感慨:当接触到微软这套程序时,代码实在是太好了,好的几乎都读不懂.很久之前就对这个套开源程序特别感兴趣,但读不明白也让人郁闷. 背景(Orchard官网): 可组装系统的CMS系统,OrChard在运 ...

  5. JavaScript学习02 基础语法

    JavaScript学习02 基础语法 JavaScript中很多基础内容和Java中大体上基本一样,所以不需要再单独重复讲了,包括: 各种算术运算符.比较运算符.逻辑运算符: if else语句.s ...

  6. Java虚拟机JVM学习02 类的加载概述

    Java虚拟机JVM学习02 类的加载概述 类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对 ...

  7. Python学习02 列表 List

    Python学习02 列表 List Python列表 List Python中的列表(List)用逗号分隔,方括号包围(comma-separated values (items) between ...

  8. Android Testing学习02 HelloTesting 项目建立与执行

    Android Testing学习02 HelloTesting 项目建立与执行 Android测试,分为待测试的项目和测试项目,这两个项目会生成两个独立的apk,但是内部,它们会共享同一个进程. 下 ...

  9. [译]:Orchard入门——安装Orchard

    原文链接:Installing Orchard 文章内容基于Orchard 1.8版本 安装Orchard的方式 主要有以下四种方式安装Orchard: 利用Microsoft Web Platfor ...

随机推荐

  1. IDEA导出jar包后运行报错 找不到或无法加载主类

    开发工具:IDEA16 运行环境:ubuntu 问题:根据网上的Idea导出jar包的方法,将我的项目导出jar包后运行报错:找不到或无法加载主类.   为了找到这个原因,我重新搭建了一个测试例子,在 ...

  2. MT【167】反复放缩

    已知数列$\{a_n\}$满足:$a_1=1,a_{n+1}=a_n+\dfrac{a_n^2}{n(n+1)}$1)证明:对任意$n\in N^+,a_n<5$2)证明:不存在$M\le4$, ...

  3. BZOJ 3609: [Heoi2014]人人尽说江南好

    3609: [Heoi2014]人人尽说江南好 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 470  Solved: 336[Submit][Sta ...

  4. Mysql(五) JDBC

    一.JDBC JDBC(Java DataBase Connectivity) 是Java 数据库连接API.    JDBC完成三件事: 与一个数据库连接          向数据库发送SQL语句 ...

  5. 解题:POJ 2888 Magic Bracelet

    题面 这题虽然很老了但是挺好的 仍然套Burnside引理(因为有限制你并不能套Polya定理),思路和这个题一样,问题主要是如何求方案. 思路是把放珠子的方案看成一张图,然后就巧妙的变成了一个经典的 ...

  6. 【CF1077F2】Pictures with Kittens 单调队列+dp

    题目大意:给定一个长度为 N 的序列,点有点权,从序列中选出恰好 X 个数,并且保证任意连续的 K 个数中均有一个被选中,求选出的点权最大是多少. 题解:此题可以作为 烽火传递+ 来处理,只不过在烽火 ...

  7. 【洛谷P1471】方差

    题目大意:维护一个有 N 个元素的序列,支持以下操作:区间加,区间询问均值,区间询问方差. 题解:可知区间均值和区间和有关,即:维护区间和就等于维护了区间均值.区间方差表达式为 \(\frac{\Si ...

  8. idea中的pom文件中的jar包下载不了,手动下载jar包的方法

    问题描述: 在pom文件中添加依赖的时候,程序怎么着都是下载不了,而且实验了各种方式: IDEA引MAVEN项目jar包依赖导入问题解决 https://www.cnblogs.com/a845701 ...

  9. webpack全局引入库

    我们在日常开发的时候会遇到一些每个页面都可能会引用到的库(例如jquery) 这可能会导致我们在每一个页面都需要写这样一个语句: import $ from 'jquery'; 可能有人会担心,最后打 ...

  10. Python的生成器进阶玩法

    Python的生成器进阶玩法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.yield的表达式形式 #!/usr/bin/env python #_*_coding:utf-8 ...