{
public ActionResult Query(string name)
{
return View();
}
}  ASP.NET 中 Url 大小寫  不嚴(yán) " /> 国产亚洲精品首页在线播放,91视频18,日韩娇小性hd

天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

ASP.NET MVC:自定義 Route 以生成小寫的 Url

  先給出本文中測(cè)試用的 controller:

public class PersonsController : Controller
{
public ActionResult Query(string name)
{
return View();
}
}

  ASP.NET 中 Url 大小寫

  不嚴(yán)格來(lái)講,ASP.NET MVC 對(duì) Url 是不敏感的,以下 Url 都是相同的,都可以訪問(wèn)到 PersonController 的 Query 方法:

  1. ~/Persons/Query
  2. ~/PERSONS/QUERY
  3. ~/persons/query

  但對(duì) MVC 的數(shù)據(jù)綁定來(lái)說(shuō),大小寫似乎還是有區(qū)別的:

  1. ~/Persons/Query?Name=Bob
  2. ~/Persons/Query?Name=bob

  對(duì)以上兩個(gè) Url,Query 中 name 參數(shù)會(huì)接收到兩個(gè)不同值:Bobbob。Action 中的參數(shù)只是原樣接收,并沒(méi)有作任何處理。至于name 字符串的大小寫是否敏感要看具體的應(yīng)用了。

  再回頭看前面的三個(gè) Url:

  1. ~/Persons/Query: 是 MVC 中默認(rèn)生成的,因?yàn)樵?.NET 中方法命名通常采用 PascalCase;
  2. ~/PERSONS/QUERY: 全部大寫,這種寫法很不友好,很難讀,應(yīng)該杜絕采用這種方式;
  3. ~/persons/query:這種方式比較好,易讀,也是大多數(shù)人選擇的方式。

  本文探討如何在 MVC 中使用第三種方式,也就是小寫(但不完全小寫),目標(biāo)如下:

  在不影響程序正常運(yùn)行的前提下,將所有能小寫的都小寫,如:

  ~/persons/query?name=Bob&age=18

  ~/persons/query/name/Bob/age/18

  MVC 中 Url 的生成

  在 View 中生成超級(jí)鏈接有多種方式:

<%: Html.ActionLink("人員查詢", "Query", "Persons", new { name = "Bob" }, null) %>
<%: Html.RouteLink("人員查詢", new { controller = "Persons", action = "Query", name = "Bob" })%>
<a href="<%:Url.Action("Query", "Persons", new { name="Bob" }) %>">人員查詢</a>

  在 Action 中,可以使用 RedirectTo 來(lái)調(diào)轉(zhuǎn)至新的頁(yè)面:

return RedirectToAction("Query", "Persons", new { name = "Bob" });
return RedirectToRoute(new { controller = "Persons", action = "Query", name = "Bob" });

  ActionLink、RouteLink、RedirectToAction 和 RedirectToRouter 都會(huì)生成 Url,并最終顯示在瀏覽器的地址欄中。

  這四個(gè)方法都有很多重載,想從這里下手控制 Url 小寫實(shí)在是太麻煩了。當(dāng)然也不可行,因?yàn)榭赡苓€有其它方式來(lái)生成 Url。

  MVC 是一個(gè)非常優(yōu)秀的框架,但凡優(yōu)秀的框架都會(huì)遵循 DRY(Don't repeat yourself) 原則,MVC 也不例外。MVC 中 RouteBase 負(fù)責(zé) Url 的解析和生成:

public abstract class RouteBase
{
public abstract RouteData GetRouteData(HttpContextBase httpContext);
public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
}

  GetRouteData 用來(lái)解析 Url,GetVirtualPath 用來(lái)生成 Url。ActionLink、RouteLink、RedirectToAction 和 RedirectToRouter 內(nèi)部都會(huì)調(diào)用 GetVirtualPath 方法來(lái)生成 Url。

  因此我們的入手點(diǎn)就是 GetVirtualPath 方法。

  自定義 Route 以生成小寫的 Url

  MVC 中 RouteBase 的具體實(shí)現(xiàn)類是 Route,我們經(jīng)常在 Global.asax 中經(jīng)常使用:

public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
//...
}

  MapRoute 返回 Route,MapRoute 有很多重載,用來(lái)簡(jiǎn)化我們構(gòu)建 Route 的過(guò)程。

  Route 類沒(méi)有給我們提供可直接擴(kuò)展的地方,因此我們只能自定義一個(gè)新的 Route 來(lái)實(shí)現(xiàn)我們的小寫 Url。但處理路由的細(xì)節(jié)也是相當(dāng)麻煩的,因此我們最簡(jiǎn)單的方式就是寫一個(gè)繼承自 Route 的類,然后重寫它的 GetVirtualPath 方法:

public class LowerCaseUrlRoute : Route
{
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//在此處進(jìn)行小寫處理
return base.GetVirtualPath(requestContext, values);
}
}

  再來(lái)看下我們的目標(biāo):

  ~/persons/query?name=Bob&age=18

  ~/persons/query/name/Bob/age/18

  其實(shí)我們只需要進(jìn)行兩步操作:

  1. 將路由中的 area、controller、action 的值都變成小寫;
  2. 將路由中其它鍵值對(duì)的鍵變成小寫,如:Name=Bob 中的 Name。

  那我們先來(lái)完成這個(gè)功能吧:

private static readonly string[] requiredKeys = new [] { "area", "controller", "action" };

private void LowerRouteValues(RouteValueDictionary values)
{
foreach (var key in requiredKeys)
{
if (values.ContainsKey(key) == false) continue;

var value = values[key];
if (value == null) continue;

var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
if (valueString == null) continue;

values[key] = valueString.ToLower();
}

var otherKyes = values.Keys
.Except(requiredKeys, StringComparer.InvariantCultureIgnoreCase)
.ToArray();

foreach (var key in otherKyes)
{
var value = values[key];
values.Remove(key);
values.Add(key.ToLower(), value);
}
}

  GetVirtualPath 生成 Url 時(shí),會(huì)將 requestContext.RouteData.Values、values(第二個(gè)參數(shù)) 以及 Defaults(當(dāng)前 Router 的默認(rèn)值)三個(gè) RouteValueDictionary 進(jìn)行合并,如在 View 寫了如下的一個(gè) ActionLinks:

<%: Html.ActionLink("查看") %>

  生成的 Html 代碼可能是:

<a href="/Home/Details">查看</a>

  因?yàn)闆](méi)有指定 Controller,MVC 會(huì)自動(dòng)使用當(dāng)前的,即從 requestContext.RouteData.Values 中獲取 Controller,得到 ”Home“;”Details“來(lái)自 values;如果連 ActionLink 中 Action 也不指定,那將會(huì)從 Defaults 中取值。

  因此我們必須將這三個(gè) RouteValueDictionary 都進(jìn)行處理才能達(dá)到我們的目標(biāo):

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
LowerRouteValues(requestContext.RouteData.Values);
LowerRouteValues(values);
LowerRouteValues(Defaults);
return base.GetVirtualPath(requestContext, values);
}

  再加上幾個(gè)構(gòu)造函數(shù),完整的 LowerCaseUrlRoute 如下:

public class LowerCaseUrlRoute : Route
{
private static readonly string[] requiredKeys = new [] { "area", "controller", "action" };

public LowerCaseUrlRoute(string url, IRouteHandler routeHandler)
: base(url, routeHandler) { }

public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
: base(url, defaults, routeHandler){ }

public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler) { }
public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
: base(url, defaults, constraints, dataTokens, routeHandler) { }

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
LowerRouteValues(requestContext.RouteData.Values);
LowerRouteValues(values);
LowerRouteValues(Defaults);
return base.GetVirtualPath(requestContext, values);
}

private void LowerRouteValues(RouteValueDictionary values)
{
foreach (var key in requiredKeys)
{
if (values.ContainsKey(key) == false) continue;

var value = values[key];
if (value == null) continue;

var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
if (valueString == null) continue;

values[key] = valueString.ToLower();
}

var otherKyes = values.Keys
.Except(requiredKeys, StringComparer.InvariantCultureIgnoreCase)
.ToArray();

foreach (var key in otherKyes)
{
var value = values[key];
values.Remove(key);
values.Add(key.ToLower(), value);
}
}
}

  有了 LowerCaseUrlRoute,我們就可以修改 Global.asax 文件中的路由了。

  創(chuàng)建 LowerCaseUrlRouteMapHelper

  這一步不是必須的,但有了這個(gè) MapHelper 我們?cè)谛薷?Global.asax 文件中的路由時(shí)可以非常方便:

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapLowerCaseUrlRoute( //routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}

  尤其是已經(jīng)配置了很多路由的情況下,其代碼如下:

public static class LowerCaseUrlRouteMapHelper
{
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this RouteCollection routes, string name, string url){
return routes.MapLowerCaseUrlRoute(name, url, null, null);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this RouteCollection routes, string name, string url, object defaults){
return routes.MapLowerCaseUrlRoute(name, url, defaults, null);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this RouteCollection routes, string name, string url, string[] namespaces){
return routes.MapLowerCaseUrlRoute(name, url, null, null, namespaces);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this RouteCollection routes, string name, string url, object defaults, object constraints){
return routes.MapLowerCaseUrlRoute(name, url, defaults, constraints, null);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces){
return routes.MapLowerCaseUrlRoute(name, url, defaults, null, namespaces);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces){
if (routes == null) throw new ArgumentNullException("routes");
if (url == null) throw new ArgumentNullException("url");
LowerCaseUrlRoute route2 = new LowerCaseUrlRoute(url, new MvcRouteHandler());
route2.Defaults = new RouteValueDictionary(defaults);
route2.Constraints = new RouteValueDictionary(constraints);
route2.DataTokens = new RouteValueDictionary();
LowerCaseUrlRoute item = route2;
if ((namespaces != null) && (namespaces.Length > 0))
item.DataTokens["Namespaces"] = namespaces;
routes.Add(name, item);
return item;
}

public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this AreaRegistrationContext context, string name, string url){
return context.MapLowerCaseUrlRoute(name, url, null);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this AreaRegistrationContext context, string name, string url, object defaults){
return context.MapLowerCaseUrlRoute(name, url, defaults, null);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this AreaRegistrationContext context, string name, string url, string[] namespaces){
return context.MapLowerCaseUrlRoute(name, url, null, namespaces);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints) {
return context.MapLowerCaseUrlRoute(name, url, defaults, constraints, null);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this AreaRegistrationContext context, string name, string url, object defaults, string[] namespaces){
return context.MapLowerCaseUrlRoute(name, url, defaults, null, namespaces);
}
public static LowerCaseUrlRoute MapLowerCaseUrlRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints, string[] namespaces)
{
if ((namespaces == null) && (context.Namespaces != null))
namespaces = context.Namespaces.ToArray<string>();
LowerCaseUrlRoute route = context.Routes.MapLowerCaseUrlRoute(name, url, defaults, constraints, namespaces);
route.DataTokens["area"] = context.AreaName;
bool flag = (namespaces == null) || (namespaces.Length == 0);
route.DataTokens["UseNamespaceFallback"] = flag;
return route;
}
}

  總結(jié)

  大功告成,如果你感興趣,不妨嘗試下!寫到這里吧,如果需要,請(qǐng)下載本文中的示例代碼:MvcLowerCaseUrlRouteDemo.rar(209KB)如果你有其它辦法,歡迎交流!

NET技術(shù)ASP.NET MVC:自定義 Route 以生成小寫的 Url,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 亚洲精品线在线观看 | 成人国产亚洲欧美成人综合网 | 国家产午夜精品无人区 | 总攻催眠受的高h巨肉np | 国产亚洲精品精品国产亚洲综合 | A级韩国乱理伦片在线观看 a级成人免费毛片完整版 | 欧美手机在线 | 最新男同鸭子ktv | 久久大胆视频 | 九九久久精品国产 | 一本到高清视频在线观看三区 | 3a丝袜论坛 | 欧美日韩一区二区三区四区 | 91羞羞视频 | 无遮18禁在线永久免费观看挡 | 女侠含泪巨臀迎合79 | 两个女人互添下身高潮自视频 | 男助理憋尿PLAY灌尿BL出去 | 国产亚洲精品久久久999无毒 | 精品一成人岛国片在线观看 | 一本久道视频无线视频 | 国外色幼网 | 国产真实强被迫伦姧女在线观看 | 国产MD视频一区二区三区 | 青柠在线观看视频在线高清完整 | 一个人的HD高清在线观看 | 亚洲精品综合在线影院 | 午夜国产羞羞视频免费网站 | 亚洲精品色情APP在线下载观看 | 伊人久久大香线蕉综合亚洲 | 果冻传媒视频在线播放 免费观看 | 年轻的母亲4线在线观看完整 | 久久电影精品久久99久久 | 无码区国产区在线播放 | 中俄两军在日本海等上空战略巡航 | 国产精品福利片 | 小泽玛丽av无码观看 | 三级aa久久| 香蕉eeww99国产精品 | 日本亚洲欧洲免费旡码 | 午夜一个人在线观看完整版 |