>  기사  >  백엔드 개발  >  역사상 가장 포괄적인 ASP.NET MVC 라우팅 구성

역사상 가장 포괄적인 ASP.NET MVC 라우팅 구성

巴扎黑
巴扎黑원래의
2017-04-09 11:15:115332검색

먼저 기본 라우팅 규칙 원칙에 대해 이야기해 보겠습니다. 기본 라우팅 규칙은 특별한 것부터 일반적인 것까지 배열되어 있습니다. 즉, 가장 특별한(비주류) 규칙이 맨 앞에 있고 가장 일반적인(모든 경우에 적용되는) 규칙이 맨 뒤에 있습니다. 일치하는 라우팅 규칙도 이 순서를 따르기 때문입니다. 거꾸로 쓰면 라우팅 규칙을 제대로 써도 404를 기다리게 됩니다.

XD 먼저 URL의 구조에 대해 이야기해 보겠습니다. 사실 이것은 구조가 아니라 문법적인 특징일 뿐입니다.

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를 방문하면 응답에는 문제가 없습니다. 세 가지 예약어인 컨트롤러, 액션, 영역은 정적 변수에 배치하면 안 됩니다.

3. 일반 변수 URL 세그먼트를 맞춤설정하세요(음, 이 번역은 귀하의 IQ를 드러냅니다)

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

이 경우 /Home/Index에 접근하면 세 번째 세그먼트(id)에는 값이 없기 때문에 이 파라미터는 라우팅 규칙에 따라 DefaultId

로 설정됩니다. 이는 viewbag을 사용하여 제목

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

에 값을 할당하면 명확하게 볼 수 있습니다. 사진은 더 이상 게시되지 않으며 결과적으로 제목이 DefaultId로 표시됩니다. 컨트롤러에서 값을 할당해야 한다는 점에 유의하세요. 뷰에서 값을 할당하면 컴파일되지 않습니다.

4. 기본 경로 불러오기

그런 다음 기본 경로로 돌아갑니다. UrlParameter.Optional은 선택적 URL 세그먼트라고 합니다. 경로에 해당 매개변수가 없으면 ID는 null이 됩니다. 원본 기사에 따르면 이 선택적 URL 세그먼트를 사용하여 우려사항을 분리할 수 있습니다. 실제로 지금 경로에서 매개변수 기본값을 직접 설정하는 것은 그리 좋지 않습니다. 제가 이해한 바에 따르면 실제 매개변수는 사용자가 전송하며 우리가 하는 일은 형식적인 매개변수 이름을 정의하는 것뿐입니다. 그러나 매개변수에 기본값을 할당해야 한다면 구문 설탕을 사용하여 이를 액션 매개변수에 작성하는 것이 좋습니다. 예:

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

5. 가변 길이 라우팅.

아아아아

여기서 id와 마지막 세그먼트는 모두 변수이므로 /Home/Index/dabdafdaf는 /Home/Index//abcdefdjldfiaeahfoeiho와 동일하며 /Home/Index/All/Delete/Perm/.....

6. 네임스페이스 간 라우팅

이는 네임스페이스를 인용하고 IIS 웹 사이트를 열어야 한다는 점을 상기시켜 주는 것입니다. 그렇지 않으면 404가 표시됩니다. 이것은 매우 비주류적이므로 엉망으로 만드는 것을 권장하지 않습니다.

아아아아

하지만 이렇게 작성하면 배열 순위가 특정 순서로 지정되지 않습니다. 일치하는 경로가 여러 개 있으면 오류가 보고됩니다. 그러자 저자는 개선된 글쓰기 방법을 제안했다.

아아아아

이런 방식으로 첫 번째 URL 세그먼트가 Home이 아닌 경우 처리를 위해 두 번째 URL 세그먼트로 전달됩니다. 마지막으로 이 경로를 찾을 수 없으면 후속 경로에 대한 탈출구를 남기지 않도록 설정할 수도 있습니다. 그래서 더 이상 아래를 내려다보지 않을 것입니다.

아아아아

7. 정규식 매칭 경로

rree

여러 URL 제한

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

8. 요청 방법

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

지정 9. 웹폼 지원

아아아아

자세한 내용은

을 참조하세요. Asp.Net4의 새로운 기능 라우팅을 사용하여 WebForm 애플리케이션 만들기

아니면 공식 msdn

10.MVC5의 RouteAttribute

먼저 루팅등록방법

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

에 들어갑니다. 이쪽으로

아아아

경로 기능만 유효합니다. 이 기능에는 경로 제한, 순서, 경로 이름 등도 여러 가지가 있습니다.

其他的还有路由前缀,路由默认值

[RoutePrefix("reviews")]<br>[Route("{action=index}")]<br>public class ReviewsController : Controller<br>{<br>}

 路由构造

// eg: /users/5
[Route("users/{id:int}"]
public ActionResult GetUserById(int id) { ... }
 
// eg: users/ken
[Route("users/{name}"]
public ActionResult GetUserByName(string name) { ... }

 参数限制

// eg: /users/5
// but not /users/10000000000 because it is larger than int.MaxValue,
// and not /users/0 because of the min(1) constraint.
[Route("users/{id:int:min(1)}")]
public ActionResult GetUserById(int id) { ... }
Constraint Description Example
alpha Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z) {x:alpha}
bool Matches a Boolean value. {x:bool}
datetime Matches a DateTime value. {x:datetime}
decimal Matches a decimal value. {x:decimal}
double Matches a 64-bit floating-point value. {x:double}
float Matches a 32-bit floating-point value. {x:float}
guid Matches a GUID value. {x:guid}
int Matches a 32-bit integer value. {x:int}
length Matches a string with the specified length or within a specified range of lengths. {x:length(6)}  {x:length(1,20)}
long Matches a 64-bit integer value. {x:long}
max Matches an integer with a maximum value. {x:max(10)}
maxlength Matches a string with a maximum length. {x:maxlength(10)}
min Matches an integer with a minimum value. {x:min(10)}
minlength Matches a string with a minimum length. {x:minlength(10)}
range Matches an integer within a range of values. {x:range(10,50)}
regex Matches a regular expression. {x:regex(^\d{3}-\d{3}-\d{4}$)}

具体的可以参考

Attribute Routing in ASP.NET MVC 5

 对我来说,这样的好处是分散了路由规则的定义.有人喜欢集中,我个人比较喜欢这种灵活的处理.因为这个action定义好后,我不需要跑到配置那里定义对应的路由规则

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
/// <summary>
/// If the standard constraints are not sufficient for your needs, you can define your own custom constraints by implementing the IRouteConstraint interface.
/// </summary>
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" });

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

12.访问本地文档

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="" />

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

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的从第二部分开始读好了。前面都是入门(对我来说是扯淡)。但总比国内某些写书的人好吧——把个开源项目的源代码下载下来帖到书上面来,然后标题起个深入解析XXXX,然后净瞎扯淡。最后一千多页的巨著又诞生了。Adam Freeman的风格我就很喜欢,都是实例写作,然后还在那边书里面专门写了大量的测试。

  哎没办法啊,技术差距就是这样了。

위 내용은 역사상 가장 포괄적인 ASP.NET MVC 라우팅 구성의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.