建立自己的 MVC portal (四)

前面我们介绍了如何实现一个可以支持多站点不同URL转换的Route,这里我们将实现一个继承于SiteRouteBase的实例,也就是说,在这里我们将实例化第一个进行URL转换的实例代码。首先我们先回顾一下平台Route的工作机制:

建立自己的 MVC portal (四)_第1张图片

在找到站点后,系统会直接调用站点指定的URL转换器的实例类,完成URL的转换或组成可访问的虚拟URL,首先,我们先了解一下SiteRouteBase

    /// <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);
    }

public abstract bool GetRouteData(RouteData data, string accessURL);

这个是解释虚拟URL到Controller/Action的转换器,这里移动有两个参数,RouteData data,存放转换结果,string accessURL是不含网站URL头的访问网址,例如:如果站点的URL为 http://localhost:1234,当你访问http://localhost:1234/Admin/UserList 时,系统在执行时根据URL头http://localhost:1234信息就可以找到实际的访问站点了,并将地址进行截取,将站点的实际访问信息,即“Admin/UserList”发送给站点URL转换的实例类来处理。

这样我们就可以建立多种实例类来解释,例如:以斜线作为分隔符的,也可以以下划线作为分隔符的,同样也可以通过其他方式进行的,从而完成不同站点不同解析的目的。

例如:http://localhost:1234/Admin/UserList 和 http://localhost:5555/Admin_UserList 访问的内容是一样的,只是访问的URL表现是不一样的,系统同样会根据站点设置截取掉URL头信息,将后面的访问信息通过站点Route的实例,调用其GetRouteData函数完成URL的转换,上述两个网址如果是针对http://localhost:1234和 http://localhost:5555两个网站的话,其调用Route实例的转换函数就是GetRouteData(RouteData, "Admin/UserList")和GetRouteData(RouteData, "Admin_UserList")了,由转换器自己来完成最终的解释。

好了!我们来实现第一个自己的Route:

我们先新建一个类工程

建立自己的 MVC portal (四)_第2张图片

using System.Collections.Generic;
/// <![CDATA[author : jamesvon date : 2016.4.2]]>
/// <summary>
/// CAP URL转换器,网址后以Controller为第一路径,Action为第二路径,后面紧随执行参数,?后跟随是页面参数<br />
/// 例如:http://127.0.0.1/page/news/3232332.html?from=www.baidu.com <br />
/// 其中 http://127.0.0.1 为域名区域,page 为 Controller 名称,news 为 action 名称,3232332 为新闻序号参数,?后面跟得是页面参数。
/// <remarks>
/// 这是各种路由转换器的一种,其基础类是 SiteRouteBase </remarks>
using System.Web.Routing;

namespace VonPortal.Web
{
    /// <summary>
    /// CAP URL转换器,网址后以Controller为第一路径,Action为第二路径,后面紧随执行参数,?后跟随是页面参数<br />
    /// result.Values["controller"]=Controller名称,如果没有则是Home<br />
    /// result.Values["action"]=Action名称,如果没有则是Index<br />
    /// result.Values["item"]=执行参数,以String[]对象存储,没有则为string[0]<br />
    /// result.Values["param"]=页面参数,以String[]对象存储,没有则为string[0]<br />
    /// result.Values["controller"]=Controller名称
    /// </summary>
    /// <example>http://127.0.0.1/news/view/221122.html?from=wwww.sina.com.cn</example>
    /// <seealso cref="SiteRouteBase"/>
    /// <![CDATA[This is a text]]>
    public class CAPRouter : SiteRouteBase
    {
        /// <summary>
        /// 解析一个URL
        /// </summary>>
        /// <param name="data">路由数据</param>
        /// <param name="accessURL">不含网站头的访问路径</param>
        /// <returns>路由数据</returns>
        public override bool GetRouteData(RouteData data, string accessURL)
        {
            // [{controller}]/{action}[/{key}/{key_value}..]?{param_name}={param_value}[&{param_name}={param_value}..]\
            accessURL = accessURL.Trim(new char[] { '/', ' ', '?', '&' });
            int mPos = accessURL.IndexOf('?');
            string[] path = mPos >= 0 ? accessURL.Remove(mPos).Split(new char[1] { '/' }) : accessURL.Split(new char[1] { '/' });
            string[] param = mPos >= 0 ? accessURL.Substring(mPos + 1).Split(new char[2] { '&', '=' }): null;
            // write parameters to route datas.  [{controller}]/{action}[/{key}/{key_value}..]
            int idx = 0;
            if (path.Length > 0 && path.Length % 2 == 0 && path[0] != "")
            {
                data.Values.Add("controller", path[idx]);
                idx++;
            } else data.Values.Add("controller", "Home");
            if (path.Length > 0 && path.Length % 2 == 1 && path[0] != "")
            {
                data.Values.Add("action", path[0]);
                idx++;
            } else if (path.Length > 1 && path.Length % 2 == 0 && path[1] != "")
            {
                data.Values.Add("action", path[1]);
                idx++;
            } else data.Values.Add("action", "Index");
            string key = "";
            while (idx < path.Length) {
                if (key == "") key = path[idx];
                else
                {
                    data.Values.Add(key, path[idx]);
                    key = "";
                }
                idx++;
            }
            idx = 0;
            while (param != null && idx < param.Length)
            {
                if (key == "") key = param[idx];
                else
                {
                    data.Values.Add(key, param[idx]);
                    key = "";
                }
                idx++;
            }
            return true;
        }
        /// <summary>
        /// 得到一个可访问的虚拟路径
        /// </summary>
        /// <param name="route">系统路由</param>
        /// <param name="requestContext">访问内容</param>
        /// <param name="values">执行参数</param>
        /// <returns>可访问的虚拟路径</returns>
        public override VirtualPathData GetVirtualPath(VonPortalRoute route, RequestContext requestContext, RouteValueDictionary values)
        {
            var elegantValues = new RouteValueDictionary(values);
            route.Url = "{controller}/{action}";
            foreach(KeyValuePair<string, object> kv in values)
            {
                if (kv.Key == "site") continue;
                if (kv.Key == "area") continue;
                if (kv.Key == "controller") continue;
                if (kv.Key == "action") continue;
                if (route.Url.IndexOf("{" + kv.Key + "}") > 0) continue;
                route.Url += "/" + kv.Key + "/{" + kv.Key + "}";
            }
            VirtualPathData data = route.BaseVirtualPath(requestContext, elegantValues);
            return data;
        }
    }
}

在这里我们通个这个实例完成了第一个route的编写。

你可能感兴趣的:(mvc,route,VonPortal)