這篇文章將為大家詳細講解有關ASP.NET MVC路由配置的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
先說一下基本的路由規則原則?;镜穆酚梢巹t是從特殊到一般排列,也就是最特殊(非主流)的規則在最前面,最一般(萬金油)的規則排在最后。這是因為匹配路由規則也是照著這個順序的。如果寫反了,那么即便你路由規則寫對了那照樣坐等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,response也是完全沒問題的。 controller , action , area這三個保留字就別設靜態變量里面了。
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。 注意要在控制器里面賦值,在視圖賦值沒法編譯的。
然后再回到默認路由。 UrlParameter.Optional這個叫可選URL段.路由里沒有這個參數的話id為null。 照原文大致說法,這個可選URL段能用來實現一個關注點的分離。剛才在路由里直接設定參數默認值其實不是很好。照我的理解,實際參數是用戶發來的,我們做的只是定義形式參數名。但是,如果硬要給參數賦默認值的話,建議用語法糖寫到action參數里面。比如:
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 });在這里id和最后一段都是可變的,所以 /Home/Index/dabdafdaf 等效于 /Home/Index//abcdefdjldfiaeahfoeiho 等效于 /Home/Index/All/Delete/Perm/.....
這個提醒一下記得引用命名空間,開啟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;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+" } });具體的可以看
使用Asp.Net4新特性路由創建WebForm應用
或者官方msdn
首先要在路由注冊方法那里
//啟用路由特性映射 routes.MapMvcAttributeRoutes();
這樣
[Route("Login")]route特性才有效.該特性有好幾個重載.還有路由約束啊,順序啊,路由名之類的.
[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路由配置的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。