먼저 기본 라우팅 규칙 원칙에 대해 이야기해 보겠습니다. 기본 라우팅 규칙은 특별한 것부터 일반적인 것까지 배열되어 있습니다. 즉, 가장 특별한(비주류) 규칙이 맨 앞에 있고 가장 일반적인(모든 경우에 적용되는) 규칙이 맨 뒤에 있습니다. 일치하는 라우팅 규칙도 이 순서를 따르기 때문입니다. 거꾸로 쓰면 라우팅 규칙을 제대로 써도 404를 기다리게 됩니다.
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" });
개인적으로는 첫 번째가 이해하기 쉽고, 두 번째가 디버그하기 쉽고, 세 번째가 작성하기 더 효율적이라고 생각합니다. 필요한 것을 가져가세요. 이 기사의 작성은 세 번째 유형에 편향되어 있습니다.
routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的 URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 (UrlParameter.Optional-可选的意思) );
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를 방문하면 응답에는 문제가 없습니다. 세 가지 예약어인 컨트롤러, 액션, 영역은 정적 변수에 배치하면 안 됩니다.
routes.MapRoute("MyRoute2", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });
이 경우 /Home/Index에 접근하면 세 번째 세그먼트(id)에는 값이 없기 때문에 이 파라미터는 라우팅 규칙에 따라 DefaultId
로 설정됩니다. 이는 viewbag을 사용하여 제목
ViewBag.Title = RouteData.Values["id"];
에 값을 할당하면 명확하게 볼 수 있습니다. 사진은 더 이상 게시되지 않으며 결과적으로 제목이 DefaultId로 표시됩니다. 컨트롤러에서 값을 할당해야 한다는 점에 유의하세요. 뷰에서 값을 할당하면 컴파일되지 않습니다.
그런 다음 기본 경로로 돌아갑니다. UrlParameter.Optional은 선택적 URL 세그먼트라고 합니다. 경로에 해당 매개변수가 없으면 ID는 null이 됩니다. 원본 기사에 따르면 이 선택적 URL 세그먼트를 사용하여 우려사항을 분리할 수 있습니다. 실제로 지금 경로에서 매개변수 기본값을 직접 설정하는 것은 그리 좋지 않습니다. 제가 이해한 바에 따르면 실제 매개변수는 사용자가 전송하며 우리가 하는 일은 형식적인 매개변수 이름을 정의하는 것뿐입니다. 그러나 매개변수에 기본값을 할당해야 한다면 구문 설탕을 사용하여 이를 액션 매개변수에 작성하는 것이 좋습니다. 예:
public ActionResult Index(string id = "abcd"){ViewBag.Title = RouteData.Values["id"];return View();}
여기서 id와 마지막 세그먼트는 모두 변수이므로 /Home/Index/dabdafdaf는 /Home/Index//abcdefdjldfiaeahfoeiho와 동일하며 /Home/Index/All/Delete/Perm/.....
이는 네임스페이스를 인용하고 IIS 웹 사이트를 열어야 한다는 점을 상기시켜 주는 것입니다. 그렇지 않으면 404가 표시됩니다. 이것은 매우 비주류적이므로 엉망으로 만드는 것을 권장하지 않습니다.
아아아아하지만 이렇게 작성하면 배열 순위가 특정 순서로 지정되지 않습니다. 일치하는 경로가 여러 개 있으면 오류가 보고됩니다. 그러자 저자는 개선된 글쓰기 방법을 제안했다.
아아아아이런 방식으로 첫 번째 URL 세그먼트가 Home이 아닌 경우 처리를 위해 두 번째 URL 세그먼트로 전달됩니다. 마지막으로 이 경로를 찾을 수 없으면 후속 경로에 대한 탈출구를 남기지 않도록 설정할 수도 있습니다. 그래서 더 이상 아래를 내려다보지 않을 것입니다.
아아아아routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("MyRoute","{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "URLsAndRoutes.AdditionalControllers", "UrlsAndRoutes.Controllers" });
자세한 내용은
을 참조하세요. Asp.Net4의 새로운 기능 라우팅을 사용하여 WebForm 애플리케이션 만들기
아니면 공식 msdn
먼저 루팅등록방법
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定义好后,我不需要跑到配置那里定义对应的路由规则
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" });
比如这个就用来匹配是否是用谷歌浏览器访问网页的。
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="" />
routes.IgnoreRoute("Content/{filename}.html");
文件名还可以用 {filename}占位符。
IgnoreRoute方法是RouteCollection里面StopRoutingHandler类的一个实例。路由系统通过硬-编码识别这个Handler。如果这个规则匹配的话,后面的规则都无效了。 这也就是默认的路由里面routes.IgnoreRoute("{resource}.axd/{*pathInfo}");写最前面的原因。
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!