Asp.Net MVC4 系列--進階篇之路由 (2)
上一篇介紹了Asp.Net MVC 中,從Http Pipeline上接收到請求如何匹配,匹配限制,以及如何控制在指定名稱空間查詢,解析出controller和action,並傳參。
這篇主要介紹如何使用路由完成url生成,實現頁面跳轉,以及customize一個路由。
在view中生成一個url連線
路由配置使用預設生成的:
routes.MapRoute(
name:"Default",
url:"{controller}/{action}/{id}",
defaults: new { controller ="Home", action = "Index", id = UrlParameter.Optional }
);
最簡單的方法是使用Html.ActionLink ,在home View裡新增程式碼:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"content="width=device-width" />
<title>ActionName</title>
</head>
<body>
<div>The controller is:@ViewBag.Controller</div>
<div>The action is: @ViewBag.Action</div>
<div>
@Html.ActionLink("This is an outgoing URL", "CustomVariable")
</div>
</body>
</html>
這樣就會生成:
<a href="/Home/CustomVariable">This is anoutgoing URL</a>
這樣,實際上是生成了在當前controller內,指向另一個action的url。
使用Html.ActionLink生成連結的好處是什麼,可以根據當前的路由配置,自動維護生成好的url,上例使用的是預設配置。例如如果路由配置改為:
routes.MapRoute("NewRoute","App/Do{action}",
new { controller = "Home" });
使用同樣的程式碼:
@Html.ActionLink("This is an outgoing URL","CustomVariable")
此時url連線就會生成為:
<a href="/App/DoCustomVariable">This is anoutgoing URL</a>
因為當我們訪問home controller時,NewRoute 在預設路由之前被匹配到了,就會拿它的pattern來生成url了。
當一個請求來時,路由會檢測:
1.Pattern
2.路由限制
3.Assign給匿名物件的預設值,就是解析存在Route Dictionary 裡面的那些值
跳轉到其他controller
最簡單的方式:
@Html.ActionLink("Thistargets another controller", "Index", "Admin")
直接傳入第二個引數,指向”admin”controller
生成url連線,同時傳參
對於同一個controller:
@Html.ActionLink("This is anoutgoing URL",
"CustomVariable", new {id = "Hello" })
跨controller傳值:
@Html.ActionLink("Click me to go to anotherarea","Index", "Test",new {Id="aaa"},null)
注意,如果路由成功匹配了傳值的引數名稱,那麼url就會以匹配的格式生成;如果路由匹配成功,可是傳的值沒有在路由模式中指定,那麼就會以?param=value的形式傳值。例如,對於以上actionlink,如果是路由:
routes.MapRoute("NewRoute","App/Do{action}",
new { controller ="Home" })
那麼生成的url連線就是:
<a href="/Home/CustomVariable?id=Hello">This is an outgoingURL</a>
如果對於路由:
routes.MapRoute("MyRoute","{controller}/{action}/{id}",
new { controller ="Home", action = "Index",
id = UrlParameter.Optional });
那麼生成的url就是:
<a href="/Home/CustomVariable/Hello">This is an outgoingURL</a>
設定html屬性
簡單的,還是同樣使用Html.ActionLink:
@Html.ActionLink("This is anoutgoing URL",
"Index","Home", null, new {id = "myAnchorID",
@class = "myCSSClass"})
這樣就可以生成一個連線,class設為了myCssClass
<aclass="myCSSClass"href="/"id="myAnchorID">This is an outgoing URL</a>
生成一個絕對路徑的url連線
@Html.ActionLink("This is anoutgoing URL", "Index", "Home",
"https","myserver.mydomain.com", " myFragmentName",
new { id = "MyId"},
new { id ="myAnchorID", @class = "myCSSClass"})
生成:
<a class="myCSSClass"
href="https://myserver.mydomain.com/Home/Index/MyId#myFragmentName"
id="myAnchorID">This is an outgoing URL</a>
通常,不建議生成絕對路徑的url,如需指向外部連線,可以直接使用html標籤。
生成URL
有些場景,只需要生成一個連線,而不想和html.ActionLink建立耦合,那麼就可以使用Url.Action:
@Url.Action("Index","Home", new { id = "MyId" })
對於預設route({controller}/{action}/{id})生成:
Home/Index/MyId
在action內生成url
public ViewResult MyActionMethod() {
string myActionUrl = Url.Action("Index",new { id = "MyID" });
string myRouteUrl =Url.RouteUrl(new { controller = "Home", action = "Index"});
//... do something with URLs...
return View();
}
當然,更推薦簡單的使用 RedirectToAction(),返回值為RedirectToRouteResult:
public RedirectToRouteResult MyActionMethod() {
return RedirectToAction("Index");
}
如果想跳出當前的controller,使用另一個過載:
public RedirectToRouteResult TestRedirect()
{
returnRedirectToAction("TestAction", "AnotherController");
}
如果這個請求handle不掉,也不想跳到哪個controller,那就還給route吧(這種場景不多):
public RedirectToRouteResult MyActionMethod() {
return RedirectToRoute(new {
controller = "Home",
action = "Index",
id = "MyID" });
}
自定義route system
如果當前route的行為還不能滿足場景需要,那麼可以自定義route,例如,對於剛從asp.netweb form移植到mvc上的網站,對於舊版本的url,我們也需要支援。
建立controller:
namespace UrlsAndRoutes.Controllers {
public class LegacyController : Controller {
public ActionResult GetLegacyURL(string legacyURL) {
return View((object)legacyURL);
}
}
}
這個controller接收傳來的url,列印出當前的url(真正的行為應該是顯示出該檔案內容)。
View裡面顯示出controller拿來的url值:
@model string
@{
ViewBag.Title = "GetLegacyURL";
Layout = null;
}
<h2>GetLegacyURL</h2>
The URL requested was: @Model
完成了簡單的controller和view,重點在於後面的route。
public class LegacyRoute : RouteBase {
private string[] urls;
public LegacyRoute(params string[] targetUrls) {
urls = targetUrls;
}
public override RouteData GetRouteData(HttpContextBase httpContext) {
RouteData result = null;
string requestedURL =
httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase)) {
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Legacy");
result.Values.Add("action", "GetLegacyURL");
result.Values.Add("legacyURL", requestedURL);
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext,
RouteValueDictionary values) {
return null;
}
建立一個類,繼承了routeBase,重點在後面的那兩個需要重寫的方法:
GetRouteData和GetVirtualPath
對於getroutedata,我們做的操作時從httpcontext物件裡拿當前的requesturl,如果是舊版本url裡面的,那麼直接就把controller指向legacy,action指向GetLegacyURL,並且把引數一起給了:LegacyURL設為當前的url。如果這個請求不是舊版本url裡面,那麼簡單的返回null,讓其他的route物件來handle吧。
對於GetVirtualPath,用於生產Url時,先簡單的返回null,後面章節會介紹如何生成url。
最後,註冊一下自定義的route:
routes.Add(new LegacyRoute(
"~/articles/test1 ",
"~/old/.NET_1.0_Class_Library"));
可以看到,自定義的route已經生效了。
在自定義route中生成URL
把剛才那個GetVirtualPath的函式做個簡單實現:
public override VirtualPathData GetVirtualPath(RequestContext requestContext,
RouteValueDictionary values) {
VirtualPathData result = null;
if(values.ContainsKey("legacyURL") &&
urls.Contains((string)values["legacyURL"],StringComparer.OrdinalIgnoreCase)) {
result = newVirtualPathData(this,
new UrlHelper(requestContext)
.Content((string)values["legacyURL"]).Substring(1));
}
return result;
}
函式功能:把傳入的匿名物件的legacyURL的值做字串擷取,把首字元濾掉。
在view加入程式碼:
@Html.ActionLink("Clickme", "GetLegacyURL",
new { legacyURL = "~/articles/Windows_3.1_Overview" })
就會生成:
<a href="/articles/Windows_3.1_Overview">Click me</a>
自定義Route Handler
前面的例子,我們都是用MvcRouteHandler,對於場景:http請求需要被httphandler來處理掉,那麼就需要customize一個routehandler了。
1.提供一個類繼承IRouteHandler
public class CustomRouteHandler : IRouteHandler {
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
return new CustomHttpHandler();
}
}
2.準備好HttpHandler
public class CustomHttpHandler : IHttpHandler {
public bool IsReusable {
get { return false; }
}
public void ProcessRequest(HttpContext context) {
context.Response.Write("Hello");
}
}
用於展示,這個handler拿到httpcontext後僅僅列印出hello。
3. 註冊一個路由,對於相應的pattern,指向這個routehandler
routes.Add(new Route("SayHello", new CustomRouteHandler()));
訪問SayHello,驗證結果:
相關文章
- Asp.Net MVC4 系列--進階篇之Model(2)ASP.NETMVC
- Asp.Net MVC4 系列--進階篇之Helper(2)ASP.NETMVC
- Asp.Net MVC4 系列-- 進階篇之路由(1)ASP.NETMVC路由
- Asp.Net MVC4 系列--進階篇之Controller(2)ASP.NETMVCController
- Asp.Net MVC4系列--進階篇之AJAXASP.NETMVC
- Asp.Net MVC4 系列--進階篇之ViewASP.NETMVCView
- Asp.Net MVC4 系列--進階篇之Model(1)ASP.NETMVC
- Asp.Net MVC4系列--進階篇之Helper(1)ASP.NETMVC
- Asp.Net MVC 系列--進階篇之FilterASP.NETMVCFilter
- vue2進階篇:vue-router之命名路由Vue路由
- Asp.Net MVC系列--進階篇之controller(1)ASP.NETMVCController
- Asp.Net MVC4 系列--基礎篇(1)ASP.NETMVC
- Asp.Net MVC4系列---基礎篇(5)ASP.NETMVC
- Asp.Net MVC4系列---基礎篇(4)ASP.NETMVC
- 【webpack 系列】進階篇Web
- React進階篇2React
- Dagger 2 系列(五) -- 進階篇:@Scope 和 @Singleton
- Asp.Net MVC 系列--基礎篇(2)ASP.NETMVC
- Sanic 路由進階路由
- 測開之函式進階· 第2篇《純函式》函式
- Dagger2進階篇(二)
- .NET進階系列之四:深入DataTable
- 帶你深度解鎖Webpack系列(進階篇)Web
- 正規表示式系列之中級進階篇
- SpringCloud-OAuth2(三):進階篇SpringGCCloudOAuth
- 【asp.net core 系列】2 控制器與路由的恩怨情仇ASP.NET路由
- Java多執行緒之進階篇Java執行緒
- Membership三步曲之進階篇
- Java進階篇 設計模式之十四 ----- 總結篇Java設計模式
- to debug asp.net mvc4ASP.NETMVC
- Asp.NET Web API 2系列(二):靈活多樣的路由配置ASP.NETWebAPI路由
- 你所不知道的ASP.NET Core進階系列(三)ASP.NET
- create table進階學習系列(十一)之cluster
- Linux ACL 許可權之進階篇Linux
- Vue開發之路由進階Vue路由
- ASP.NET進階:認清控制元件 之 Button (轉)ASP.NET控制元件
- 高階前端進階系列 - webview前端WebView
- TypeScript極速完全進階指南-2中級篇TypeScript