zoukankan      html  css  js  c++  java
  • mvc3之自定义类实现路由配置和URL的生成

    在mvc中路由的配置,直接关系着我们的请求访问的控制器和方法;url对seo有着重要作用,全靠mvc内部定义的配置路由和生成url的方法在有的时间是不够的,本文就来了解一下自定义配置路由和url的生成。

    一、RouteBase类简介

    在新建一个mvc项目后,打开global文件,可以看到路由的注册是使用一个RouteCollection类型的参数来实现的。按F12转到定义会发现,其继承了Collection<RouteBase>,除了一些MapRoute等一些方法之外还有一个Add方法,其签名为:

            public void Add(string name, RouteBase item);

    实际上就是一个标记路由的名字,还有一个是RouteBase类,按F12,其对应的有两个方法:

    //当在派生类中重写时,会返回有关请求的路由信息。
    public abstract RouteData GetRouteData(HttpContextBase httpContext);
    
    //当在派生类中重写时,会检查路由是否与指定值匹配,如果匹配,则生成一个 URL,然后检索有关该路由的信息
    public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);

    第一个方法:通过处理请求信息httpContext,来指定通过哪个控制器和方法处理请求的;第二个方法用来指定请求页的连接生成的URL.下面就通过一个实例来说明以上两个方法的使用。

    二、使用RouteBase的方法

    2.1需求说明

    为了让url更加一目了然,在列表分页时,我们通过使用如下URL:http://www.***.com/分类/List/Page/n,意思就是某个分类的第n页列表。与此同时,我们对应的上一页,下一页生成对应的URL分别为http://www.***.com/分类/List/Page/n-1,http://www.***.com/分类/List/Page/n+1。下面以产品分类列表分页为例,即http://localhost:***/Product/List/page/n。当然该需求应该有更好的解决方案,在此仅为了说明RouteBase的使用。为了演示,我们先新建一个MVC项目,在controllers文件夹添加一个ProductController,并简单添加一个类表方法:

    public ActionResult List(int page = 1)
            {
                ViewBag.count = page;
                ViewBag.content=""+page+"";
                return View();
            }

    并添加对应的视图,

    @{
        ViewBag.Title = "List";
    }
    <h2>产品列表</h2>
    <a href="@Url.Action("Product", "List", new { page = "page", id = Convert.ToInt32(ViewBag.count) - 1 })">上一页</a>
    <a href="@Url.Action("Product","List",new {page="page",id= ViewBag.count})"> @ViewBag.content</a>
    <a href="@Url.Action("Product", "List", new { page = "page", id = Convert.ToInt32(ViewBag.count) + 1 })">下一页</a>

    然后添加一个文件夹Infranstructure,并新建一个类MyHelper,然后让其继承RouteBase类,如图:

    image

    2.2GetRouteData的使用

    为了配置路由,我们不使用MapRoute方法,可以把global文件里面的默认的MapRoute去掉,我们使用上面的GetRouteData方法,我们通过httpcontext来指定控制器里面的方法以到达处理请求的目的。代码如下:

    public class MyHelper : RouteBase
        {
            public override RouteData GetRouteData(HttpContextBase httpContext)
            {
                //指定处理请求的路由对象为MvcRouteHandler对象
                var data = new RouteData(this, new MvcRouteHandler());
                //接受请求的url,并对其指定controller和action以及action的参数
                string strUrl = httpContext.Request.RawUrl;
                string[] arry = strUrl.Split('/');
                if (arry.Length > 4)
                {
                    data.Values.Add("controller", "Product");
                    data.Values.Add("action", "List");
                    data.Values.Add(arry[3], arry[4]);
                    return data;
                }
                /*如果不符合要求的url,返回null,以便使用其他路由匹配,进而指定
                controller和action以及action的参数*/
                return null;
            }
            public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
            {
                //我们暂且返回一个null
    return null;
           }
       }

    因为开始的时间,我们去掉了MapRoute,现在我们要使用Add方法,所以在global文件中添加

    routes.Add(new MyHelper());

    现在运行程序,并在地址栏输入http://localhost:3519/Product/List/Page/1,效果图如下:

    image

    此时的请求已经通过我们的自定义路由生效,但是我们发现,上一页和下一页的连接不是我们想要的,如果想达到我们的要求,那么我们就需要使用GetVirtualPath方法,对该请求页的连接生成指定的URL。

    2.3 GetVirtualPath的使用

    废话不多说,还是把代码贴出来,部分说明见注释:

            /// <summary>
            /// 为指定请求页生成特定的url的样子
            /// </summary>
            /// <param name="requestContext">请求页</param>
            /// <param name="values">请求页中的Html.Action等辅助类</param>
            /// <returns></returns>
            public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
            {
                //先判断请求是否符合要求——请求的action为List,page不能为空。
                if (requestContext.RouteData.Values["action"].ToString()=="List"&&
                    !string.IsNullOrEmpty(requestContext.RouteData.Values["page"].ToString()))
                {
                    //定义一个Url字符串
                    string strUrl = string.Empty;
                    //如果values中有四个值,做下面的操作
                    if (values.Count == 4)
                    {
                        if (Convert.ToInt32(values["id"]) >= 1)
                        {
                            strUrl = values["controller"].ToString() + "/" + values["action"].ToString() + "/" + values["page"].ToString() + "/" + values["id"].ToString();
                        }
                        else
                        {
                            strUrl = values["controller"].ToString() + "/" + values["action"].ToString() + "/" + values["page"].ToString() + "/1#";
                        }
                        return new VirtualPathData(this, strUrl);
                    }
                }
                return null;
            }

    现在运行http://localhost:3519/Product/List/Page/1页面,已经是我们想要的结果了。

    image

    注意:上面的两个方法判断的时间一定要精确的判断,否则可能指定到错误的控制器和方法上以及错误的url。再者,当不符合指定要求时要返回到null,以便使用其他的路由配置。

    三、总结

    本文主要通过一个分页的实例来说明自定义路由和URL的生成。例子或许欠佳,但是比较好理解。源码.

  • 相关阅读:
    C#操作REDIS例子
    A C# Framework for Interprocess Synchronization and Communication
    UTF8 GBK UTF8 GB2312 之间的区别和关系
    开源项目选型问题
    Mysql命令大全——入门经典
    RAM, SDRAM ,ROM, NAND FLASH, NOR FLASH 详解(引用)
    zabbix邮件报警通过脚本来发送邮件
    centos启动提示unexpected inconsistency RUN fsck MANUALLY
    rm 或者ls 报Argument list too long
    初遇Citymaker (六)
  • 原文地址:https://www.cnblogs.com/lzhp/p/3021157.html
Copyright © 2011-2022 走看看