Maison >développement back-end >Tutoriel C#.Net >La configuration de routage ASP.NET MVC la plus complète de l'histoire
Parlons d’abord des principes de base des règles de routage. Les règles de routage de base sont classées du spécial au général, c'est-à-dire que les règles les plus spéciales (non traditionnelles) se trouvent au début et les règles les plus générales (taille unique) se trouvent à la fin. En effet, les règles de routage correspondantes suivent également cet ordre. Si vous l'écrivez à l'envers, même si vous écrivez correctement les règles de routage, vous attendrez toujours 404.
XD Parlons d’abord de la structure de l’URL. En fait, il ne s’agit pas d’une structure, mais simplement d’une caractéristique grammaticale.
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" });
Personnellement, je pense que le premier est plus facile à comprendre, le second est plus facile à déboguer et le troisième est plus efficace à écrire. Prenez ce dont vous avez besoin. La rédaction de cet article est orientée vers le troisième type.
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" });
Sans routage d'espace réservé, il est prêt à l'emploi et codé en dur.
Par exemple, si vous écrivez ainsi et visitez ensuite http://localhost:XXX/Shop/OldAction.js, la réponse ne posera aucun problème. Les trois mots réservés contrôleur, action et zone ne doivent pas être placés dans des variables statiques.
routes.MapRoute("MyRoute2", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "DefaultId" });
Dans ce cas, si vous accédez à /Home/Index, car le troisième segment (id) n'a aucune valeur, ce paramètre sera défini sur DefaultId
selon les règles de routage. Cela peut être clairement vu en utilisant viewbag pour attribuer une valeur au titre
ViewBag.Title = RouteData.Values["id"];
L'image n'est plus publiée et le résultat est que le titre s'affiche comme DefaultId. Notez que vous devez attribuer des valeurs dans le contrôleur. L'attribution de valeurs dans la vue ne sera pas compilée.
Revenez ensuite à l'itinéraire par défaut. UrlParameter.Optional est appelé un segment d'URL facultatif. S'il n'y a pas de paramètre de ce type dans l'itinéraire, l'identifiant sera nul. Selon l'article original, ce segment d'URL facultatif peut être utilisé pour parvenir à une séparation des préoccupations. Il n'est en fait pas très bon de définir directement la valeur par défaut du paramètre dans l'itinéraire pour le moment. D'après ma compréhension, les paramètres réels sont envoyés par l'utilisateur et tout ce que nous faisons est de définir les noms formels des paramètres. Cependant, si vous insistez pour attribuer des valeurs par défaut aux paramètres, il est recommandé d'utiliser du sucre syntaxique pour les écrire dans les paramètres d'action. Par exemple :
public ActionResult Index(string id = "abcd"){ViewBag.Title = RouteData.Values["id"];return View();}
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
Ici, l'identifiant et le dernier segment sont tous deux variables, donc /Home/Index/dabdafdaf est équivalent à /Home/Index//abcdefdjldfiaeahfoeiho est équivalent à /Home/Index/All/Delete/Perm/.....
Ceci est un rappel de ne pas oublier de citer l'espace de noms et d'ouvrir le site Web IIS, sinon il obtiendra un 404. Ceci est très peu courant et il n’est pas recommandé de s’en occuper.
routes.MapRoute("MyRoute","{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional },new[] { "URLsAndRoutes.AdditionalControllers", "UrlsAndRoutes.Controllers" });
Mais si vous l'écrivez de cette façon, le classement du tableau ne sera pas dans un ordre particulier. S'il existe plusieurs itinéraires correspondants, une erreur sera signalée. L'auteur a ensuite proposé une méthode d'écriture améliorée.
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" });
De cette façon, si le premier segment d'URL n'est pas Home, il sera transmis au second pour traitement. Enfin, vous pouvez également définir que si cette route n'est pas trouvée, elle ne laissera pas de chemin pour les routes suivantes, donc. il ne baissera plus les yeux.
Route myRoute = routes.MapRoute("AddContollerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.AdditionalControllers" }); myRoute.DataTokens["UseNamespaceFallback"] = false;
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new { controller = "^H.*"}, new[] { "URLsAndRoutes.Controllers"});
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new { controller = "^H.*", action = "^Index$|^About$"}, new[] { "URLsAndRoutes.Controllers"});
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" });
routes.MapPageRoute("", "", "~/Default.aspx"); routes.MapPageRoute("list", "Items/{action}", "~/Items/list.aspx", false, new RouteValueDictionary { { "action", "all" } }); routes.MapPageRoute("show", "Show/{action}", "~/show.aspx", false, new RouteValueDictionary { { "action", "all" } }); routes.MapPageRoute("edit", "Edit/{id}", "~/edit.aspx", false, new RouteValueDictionary { { "id", "1" } }, new RouteValueDictionary { { "id", @"\d+" } });
Pour plus de détails, veuillez consulter
Créer une application WebForm à l'aide du nouveau routage de fonctionnalités Asp.Net4
Ou msdn officiel
Tout d'abord, accédez à la méthode d'enregistrement du routage
//启用路由特性映射 routes.MapMvcAttributeRoutes();
Par ici
[Route("Login")]
La fonctionnalité d'itinéraire n'est efficace que. Cette fonctionnalité présente plusieurs surcharges. Il existe également des contraintes de routage, l'ordre, les noms d'itinéraire, etc.
.[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的风格我就很喜欢,都是实例写作,然后还在那边书里面专门写了大量的测试。
哎没办法啊,技术差距就是这样了。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!