创建本身的 MVC portal (三)

下面咱们来创建本身的Router体系:c#

这张图清晰地讲述了.net 访问过程当中内部流程机制,固然咱们也能够经过Global.asxm中创建相应的过程进行跟踪,来验证流程的真实性。咱们能够关注其中的Routing节点部分,.net正式基于这个原理实现Router的,.net将RoutData与HttpContext合并成为RequestContext传递到IRoutHandler接口,IRoutHandler接口的实现类MvcRouteHandler接口到RequestContext参数,返回一个MvcHandler对象,而且为这个对象赋值RequestContext。缓存

这个接口的定义是在 App_Start 中的 RouteConfig.cs 定义完成的。ide

咱们先看下系统默认的Route代码:函数

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapRoute( 
        name: "Default", 
        url: "{controller}/{action}/{id}", 
        defaults: new { controller = "Home", action = "Index",  id = UrlParameter.Optional } 
    );
}

咱们要对他进行改造的目的是为了更好的配合系统的多站点的要求,也就是说为了知足不一样站点使用不一样Router的可能,咱们须要从新构建本身的Route,那么咱们就须要构建一个可根据站点不一样,支持不一样方案的Route机制。
this

为了达到这一目的,咱们须要创建一个Router的基类,经过不一样的实现方式来实现不一样的站点的不一样route的方法。url

首先平台创建一个Route用来接收系统的调用,获得URL后首先分析这个URL指向的是哪一个站点,知道了是哪一个站点了咱们就能够知道这个站点采用了何种方法来处理URL的转换,这样就能够实现不一样站点不一样URL转换的处理机制。spa

首先咱们创建一个Router基类,来解决不一样站点不一样Router的机制问题:.net

    /// <summary>
    /// 站点级URL解析基类
    /// </summary>
    public abstract class SiteRouteBase
    {
        /// <summary>
        /// 分解URL获得controller和action,将分解结果写到 RouteData 中
        /// </summary>
        /// <param name="accessURL">没有SiteURL的访问地址</param>
        /// <returns></returns>
        public abstract bool GetRouteData(RouteData data, string accessURL);
        /// <summary>
        /// 根据参数获得外部访问地址,与 GetRouteData 相对应
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public abstract VirtualPathData GetVirtualPath(VonPortalRoute route, RequestContext requestContext, RouteValueDictionary values);
    }

咱们要创建不一样的SiteRouteBase实现方法来解决URL的实际转换,同时站点信息将实际使用的方法进行绑定就能够了,也就是说咱们要创建一个Site(站点)信息,同时绑定SiteRouteBase的实现类就能够了,这里我先给一个简单代码样例,待之后具体实现:code

public class SiteInfo
{
    public string Url{get;set;}//站点的URL头
    public SiteRouteBase Translate{get;set;}//站点指定的Route的转换实例
}

咱们要创建这个路由首先来研究一下Route的系统代码,系统的路由是从RouteBase继承过来的。
orm

public abstract class RouteBase
{
    protected RouteBase();
    public bool RouteExistingFiles { get; set; }
    public abstract RouteData GetRouteData(HttpContextBase httpContext);
    public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
}

RouteBase里面主要须要实现两个主要函数,即

    public abstract RouteData GetRouteData(HttpContextBase httpContext);

    public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);

只要咱们重构这两个函数就能够了,固然这是一个可行的方案,但咱们有更简单的方法来实现这个工做,就是咱们能够从系统默认的路由来继承实现,Route是从RouteBase继承过来的。

    /// <summary>
    /// 平台Route
    /// </summary>
    public class VonPortalRoute : Route
    {
        public VonPortalRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
            : base(url, defaults, constraints, dataTokens, routeHandler)
        { }
        public override RouteData GetRouteData(System.Web.HttpContextBase httpContext)
        {
            SiteInfo site = VonPortal.Web.GlobalValues.GetSiteByUrl(httpContext.Request.Url.AbsoluteUri);   //根据 URL 获得对应的 Site,支持二级域名搜索
            var data = new RouteData(this, new MvcRouteHandler());//声明一个RouteData,添加相应的路由值
            if (site == null)   //若是没有找到该域名,证实他是第一次被访问,则进入初始化界面
            {
                data.Values.Add("controller", "Admin");
                data.Values.Add("action", "SiteEdit");
            }
            else
            {
                string accessUrl = httpContext.Request.Url.AbsoluteUri.Substring(site.SiteURL.Length);
                if (accessUrl.StartsWith("/"))
                    accessUrl = accessUrl.Remove(0, 1);
                if (!site.Translater.GetRouteData(data, accessUrl)) return null;
            }
            data.Values.Add("site", site);
            return data;
        }
        public VirtualPathData BaseVirtualPath(RequestContext requestContext, RouteValueDictionary elegantValues)
        {
            return base.GetVirtualPath(requestContext, elegantValues);
        }
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            SiteInfo site = (SiteInfo)requestContext.RouteData.Values["site"];
            if (site == null) return new VirtualPathData(this, "");
            else return site.Translater.GetVirtualPath(this, requestContext, values);
        }
        
    }

这里咱们省略了站点信息的系统缓存部分,即VonPortal.Web.GlobalValues.GetSiteByUrl(httpContext.Request.Url.AbsoluteUri)的代码,这段代码的含义就是根据访问的URL信息直接获得系统的站点信息site,若是没有获得则直接进入系统的Admin/SiteEdit进行新站点初始化。

相关文章
相关标签/搜索