路由配置2(转)

XD 首先说URL的构造。 其实这个也谈不上构造,只是语法特性吧。

一、命名参数规范+匿名对象

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

构造路由然后添加

            Route myRoute = new Route("{controller}/{action}", new MvcRouteHandler());
            routes.Add("MyRoute", myRoute);  

二、直接方法重载+匿名对象

            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });  

个人觉得第一种比较易懂,第二种方便调试,第三种写起来比较效率吧。各取所需吧。本文行文偏向于第三种。

1.默认路由(MVC自带)

            routes.MapRoute(
            "Default", // 路由名称
            "{controller}/{action}/{id}", // 带有参数的 URL
            new {
                controller = "Home",
                action = "Index",
                id = UrlParameter.Optional // 参数默认值 (UrlParameter.Optional-可选的意思) );
            });

2.静态URL段

            routes.MapRoute("ShopSchema2", "Shop/OldAction",
                new { controller = "Home", action = "Index" });
            routes.MapRoute("ShopSchema", "Shop/{action}", new { controller = "Home" });
            routes.MapRoute("ShopSchema2",
                "Shop/OldAction.js",
                 new { controller = "Home", action = "Index" }); 

没有占位符路由就是现成的写死的。

比如这样写然后去访问http://localhost:XXX/Shop/OldAction.js,response也是完全没问题的。 controller , action , area这三个保留字就别设静态变量里面了。

3.自定义常规变量URL段

            routes.MapRoute("MyRoute2",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = "DefaultId" }); 

这种情况如果访问 /Home/Index 的话,因为第三段(id)没有值,根据路由规则这个参数会被设为DefaultId

这个用viewbag给title赋值就能很明显看出

ViewBag.Title = RouteData.Values["id"];  

结果是标题显示为DefaultId, 注意要在控制器里面赋值,在视图赋值没法编译的。

4.再述默认路由

然后再回到默认路由。 UrlParameter.Optional这个叫可选URL段.路由里没有这个参数的话id为null。 照原文大致说法,这个可选URL段能用来实现一个关注点的分离。刚才在路由里直接设定参数默认值其实不是很好。照我的理解,实际参数是用户发来的,我们做的只是定义形式参数名。但是,如果硬要给参数赋默认值的话,建议用语法糖写到action参数里面。比如:

public ActionResult Index(string id = "abcd"){ViewBag.Title = RouteData.Values["id"];return View();}

5.可变长度路由

        routes.MapRoute("MyRoute",
                "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional
                }); 

在这里id和最后一段都是可变的,所以 /Home/Index/dabdafdaf 等效于 /Home/Index//abcdefdjldfiaeahfoeiho 等效于 /Home/Index/All/Delete/Perm/.....

6.跨命名空间路由

这个提醒一下记得引用命名空间,开启IIS网站不然就是404。这个非常非主流,不建议瞎搞。

            routes.MapRoute("MyRoute",
                "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new[] { "URLsAndRoutes.AdditionalControllers", "UrlsAndRoutes.Controllers" });  

但是这样写的话数组排名不分先后的,如果有多个匹配的路由会报错。 然后作者提出了一种改进写法。

            routes.MapRoute("AddContollerRoute",
                "Home/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new[] { "URLsAndRoutes.AdditionalControllers" });

            routes.MapRoute("MyRoute",
                "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new[] { "URLsAndRoutes.Controllers" }); 

这样第一个URL段不是Home的都交给第二个处理 最后还可以设定这个路由找不到的话就不给后面的路由留后路啦,也就不再往下找啦。

        Route myRoute = routes.MapRoute("AddContollerRoute",
            "Home/{action}/{id}/{*catchall}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[] { "URLsAndRoutes.AdditionalControllers" }
            );
            myRoute.DataTokens["UseNamespaceFallback"] = false;  

7.正则表达式匹配路由

            routes.MapRoute("MyRoute",
                "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new { controller = "^H.*" },
                new[] { "URLsAndRoutes.Controllers" }); 

约束多个URL

            routes.MapRoute("MyRoute",
                "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new { controller = "^H.*", action = "^Index$|^About$" },
                new[] { "URLsAndRoutes.Controllers" });  

8.指定请求方法

            routes.MapRoute("MyRoute",
                "{controller}/{action}/{id}/{*catchall}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new { controller = "^H.*",
                    action = "Index|About",
                    httpMethod = new HttpMethodConstraint("GET") },
                new[] { "URLsAndRoutes.Controllers" });  

9.最后还是不爽的话自己写个类实现 IRouteConstraint的匹配方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing; 

public class UserAgentConstraint : IRouteConstraint
{ 

    private string requiredUserAgent;
    public UserAgentConstraint(string agentParam)
    {
        requiredUserAgent = agentParam;
    }
    public bool Match(HttpContextBase httpContext, Route route, string parameterName,
    RouteValueDictionary values, RouteDirection routeDirection)
    {
        return httpContext.Request.UserAgent != null &&
        httpContext.Request.UserAgent.Contains(requiredUserAgent);
    }
} 
            routes.MapRoute("ChromeRoute", "{*catchall}",
                new { controller = "Home", action = "Index" },
                new { customConstraint = new UserAgentConstraint("Chrome") },
                new[] { "UrlsAndRoutes.AdditionalControllers" }); 

比如这个就用来匹配是否是用谷歌浏览器访问网页的。

10.访问本地文档

routes.RouteExistingFiles = true;
routes.MapRoute("DiskFile", "Content/StaticContent.html", new { controller = "Customer", action = "List", });
//浏览网站,以开启 IIS Express,然后点显示所有应用程序-点击网站名称-配置(applicationhost.config)-搜索UrlRoutingModule节点
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" />
//把这个节点里的preCondition删除,变成

<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" /> 

11.直接访问本地资源,绕过了路由系统

routes.IgnoreRoute("Content/{filename}.html"); 

文件名还可以用 {filename}占位符。

IgnoreRoute方法是RouteCollection里面StopRoutingHandler类的一个实例。路由系统通过硬-编码识别这个Handler。如果这个规则匹配的话,后面的规则都无效了。

这也就是默认的路由里面routes.IgnoreRoute("{resource}.axd/{*pathInfo}");写最前面的原因。

三、路由测试(在测试项目的基础上,要装moq)

PM> Install-Package Moq 

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web;
using Moq;
using System.Web.Routing;
using System.Reflection;
[TestClass]
public class RoutesTest
{
    private HttpContextBase CreateHttpContext(string targetUrl = null, string HttpMethod = "GET")
    {
        // create the mock request
        Mock<HttpRequestBase> mockRequest = new Mock<HttpRequestBase>();
        mockRequest.Setup(m => m.AppRelativeCurrentExecutionFilePath)
        .Returns(targetUrl);
        mockRequest.Setup(m => m.HttpMethod).Returns(HttpMethod);
        // create the mock response
        Mock<HttpResponseBase> mockResponse = new Mock<HttpResponseBase>();
        mockResponse.Setup(m => m.ApplyAppPathModifier(
        It.IsAny<string>())).Returns<string>(s => s);
        // create the mock context, using the request and response
        Mock<HttpContextBase> mockContext = new Mock<HttpContextBase>();
        mockContext.Setup(m => m.Request).Returns(mockRequest.Object);
        mockContext.Setup(m => m.Response).Returns(mockResponse.Object);
        // return the mocked context
        return mockContext.Object;
    } 

    private void TestRouteMatch(string url, string controller, string action, object routeProperties = null, string httpMethod = "GET")
    {
        // Arrange
        RouteCollection routes = new RouteCollection();
        RouteConfig.RegisterRoutes(routes);
        // Act - process the route
        RouteData result = routes.GetRouteData(CreateHttpContext(url, httpMethod));
        // Assert
        Assert.IsNotNull(result);
        Assert.IsTrue(TestIncomingRouteResult(result, controller, action, routeProperties));
    } 

    private bool TestIncomingRouteResult(RouteData routeResult, string controller, string action, object propertySet = null)
    {
        Func<object, object, bool> valCompare = (v1, v2) =>
        {
            return StringComparer.InvariantCultureIgnoreCase
            .Compare(v1, v2) == 0;
        };
        bool result = valCompare(routeResult.Values["controller"], controller)
        && valCompare(routeResult.Values["action"], action);
        if (propertySet != null)
        {
            PropertyInfo[] propInfo = propertySet.GetType().GetProperties();
            foreach (PropertyInfo pi in propInfo)
            {
                if (!(routeResult.Values.ContainsKey(pi.Name)
                && valCompare(routeResult.Values[pi.Name],
                pi.GetValue(propertySet, null))))
                {
                    result = false;
                    break;
                }
            }
        }
        return result;
    } 

    private void TestRouteFail(string url)
    {
        // Arrange
        RouteCollection routes = new RouteCollection();
        RouteConfig.RegisterRoutes(routes);
        // Act - process the route
        RouteData result = routes.GetRouteData(CreateHttpContext(url));
        // Assert
        Assert.IsTrue(result == null || result.Route == null);
    } 

    [TestMethod]
    public void TestIncomingRoutes()
    {
        // check for the URL that we hope to receive
        TestRouteMatch("~/Admin/Index", "Admin", "Index");
        // check that the values are being obtained from the segments
        TestRouteMatch("~/One/Two", "One", "Two");
        // ensure that too many or too few segments fails to match
        TestRouteFail("~/Admin/Index/Segment");//失败
        TestRouteFail("~/Admin");//失败
        TestRouteMatch("~/", "Home", "Index");
        TestRouteMatch("~/Customer", "Customer", "Index");
        TestRouteMatch("~/Customer/List", "Customer", "List");
        TestRouteFail("~/Customer/List/All");//失败
        TestRouteMatch("~/Customer/List/All", "Customer", "List", new { id = "All" });
        TestRouteMatch("~/Customer/List/All/Delete", "Customer", "List", new { id = "All", catchall = "Delete" });
        TestRouteMatch("~/Customer/List/All/Delete/Perm", "Customer", "List", new { id = "All", catchall = "Delete/Perm" });
    }
} 

最后还是再推荐一下Adam Freeman写的apress.pro.asp.net.mvc.4这本书。稍微熟悉MVC的从第二部分开始读好了。

时间: 2024-10-03 22:41:43

路由配置2(转)的相关文章

CIsco动态路由配置之EIGRP

Cisco配置动态路由,可以使用EIGRP(增强型内部网关路由选择协议)进行配置 EIGRP支持: 快速收敛:使用DUAL(弥散更新算法)来实现快速收敛. 带宽的有效利用:发送部分.增量的路由更新而不是发送整个路由表,从而实现带宽的有效利用. 支持多个网络层协议:使用独立于协议的模块(PDM)来支持IP,IPX,Appletalk等协议. 支持VLSM(变长子网掩码)和CIDR(无类域间路由) 思路:分别配置各个路由器的端口IP 使用EIGRP 在各自路由器配置所属的网段 R1#CONF T E

Cisco PT模拟实验(11) 路由器单臂路由配置

Cisco PT模拟实验(11) 路由器单臂路由配置 实验目的: 掌握单臂路由的配置方法 实现不同VLAN之间互相通信 深入理解VLAN通信原理及路由子接口 实验背景: 公司的技术部和销售部分处于不同的办公室,技术部和销售部的PC分处于不同的VLAN,现由于业务的需求需要销售部和技术部的主机能够相互访问,获得相应的资源,两个部门的交换机通过一台路由器进行了连接. 技术原理: VLAN能有效分割局域网,实现各网络区域之间的访问控制.但现实中,往往需要配置某些VLAN之间的互联互通.而实现不同VLA

CCNA网络工程师学习进程(7)路由器的路由配置

    前面一节已经介绍了路由器的端口配置,接着我们介绍路由器的路由配置:静态路由.默认路由和浮动路由的配置:动态路由协议的配置,包括RIP.IGRP.EIGRP和OSPF.     (1)路由器的基础深入: 1)静态路由: 静态路由是指由用户或网络管理员手工配置的路由信息. 静态路由适用于:简单的网络环境和支持DDR(Dial-on-Demand Routing)的网络中. 在DDR(按需拨号路由选择)链路中,拨号链路只在需要时才拨通,因此不能为动态路由信息表提供路由信息的变更情况.DDR允许

MVC路由配置

目录 URL Routing 的定义方式 示例准备 给片段变量定义默认值 定义静态片段 自定义片段变量 自定义片段变量的定义和取值 将自定义片段变量作为Action方法的参数 指定自定义片段变量为可选 定义可变数量的自定义片段变量 路由约束 正则表达式约束 Http请求方式约束 自定义路由约束 定义请求磁盘文件路由 生成URL链接 生成指向当前controller的action链接 生成其他controller的action链接 生成带有URL参数的链接 指定链接的Html属性 生成完整的标准链

路由配置命令

router> enable                    从用户模式进入特权模式router# disable or exit           从特权模式退出到用户模式router# show sessions             查看本机上的TELNET会话router# disconnect                关闭所有的TELNET会话router# show users                查看本机上的用户router# erase startup-

springCloud(14):使用Zuul构建微服务网关-路由端点与路由配置详解

一.Zuul的路由端点 当@EnableZuulProxy与SpringBoot Actuator配合使用时,Zuul会暴露一个路由管理端点/routes.借助这个端点,可以方便.直观地查看以及管理Zuul的路由. /routes端点的使用非常简单,使用GET方法访问该端点,即可返回Zuul当前映射的路由列表:使用POST方法访问该端点就会强制刷新Zuul当前映射的路由列表(尽管路由会自动刷新,Spring Cloud依然提供了强制立即刷新的方式). 由于spring-cloud-starter

实验十一 路由器综合路由配置

实验十一 路由器综合路由配置 一.实验目标 掌握综合路由器的配置方法: 掌握查看通过路由重分布学习产生的路由: 熟悉广域网线缆的链接方式: 二.实验背景 假设某公司通过一台三层交换机连到公司出口路由器R1上,路由器R1再和公司外的另一台路由器R2连接.三层交换机与R1间运行RIPV2路由协议,R1与R2间运行OSPF路由协议.现要做适当配置,实现公司内部主机与公司外部主机之间的相互通信. 三.技术原理 为了支持本设备能够运行多个路由协议进程,系统软件提供了路由信息从一个路由进程重分布到另一个路由

ThinkPHP仿58同城一站多城市路由配置技巧及二级域名部署技巧

ThinkPHP在PATHINFO的URL模式下,URL的格式类似于http://www.domain.com/appName/module/action 即:http://www.domain.com/分组名/模块名/方法名 或者:http://www.domain.com/模块名/方法名 然而在有些类似于58同城这样的应用中,需要分城市展示不同的页面内容,我们希望在网站域名后面紧跟一个城市目录,也即这种格式: http://www.domain.com/城市名/模块名/方法名,根据不同的城市

Swift3.0服务端开发(二) 静态文件添加、路由配置以及表单提交

今天博客中就来聊一下Perfect框架的静态文件的添加与访问,路由的配置以及表单的提交.虽然官网上有聊静态文件的访问的部分,但是在使用Perfect框架来访问静态文件时还是有些点需要注意的,这些关键点在其官方文档上并未提出.今天我们要做的事情就是通过浏览器访问静态文件,然后在静态文件中使用form表单往指定的路由上进行提交相应的数据. 一.静态文件的添加与访问 1.未使用Xcode管理的Perfect的静态文件根目录的配置 在PHP开发或者Java Web开发中,都有一个根目录来存储相应的静态文

华为静态路由配置

======================================================== IP路由基础 查看路由表 display ip routing-table interface 输出接口 nexthop   下一跳IP地址 proto     路由协议 pre       优先级 cost      开销.度量 ======================================================== 静态路由配置 配置静态路由 ip rou