ASP.NET CORE MVC 中,默認的 Route 模板是: /{controller}/{action} 。咱們能夠經過開啓 URL 小寫轉換將 URL 變爲小寫,但此方式在 Controller 或者 Action 爲一個詞組時,生成的 URL 並不友好。假設咱們有 UserController 和 AddUser 方法,則框架生成的 URL 多是: /User/AddUser ,在開啓小寫轉換的狀況下多是下面的結果: /user/adduser 。包含大寫字符的 URL 並無問題,可是小寫的 URL 更加常規,而徹底轉換小寫形成的問題就是 URL 的可讀性不好。本文將提供一些代碼,幫助框架生成減號分隔樣式的 URL ,當應用了這些代碼之後,生成的 URL 相似這樣: /user/add-user 。 微軟爲咱們提供了 RouteAttribute ,能夠對 Controller 或者 Action 進行標記,以達到自定義訪問路徑的目的。這種方式很是強大,但在項目較大的狀況下使用起來有些繁雜。畢竟手工對每個 Controller 和 Action 進行標記也有不小的工做量。 ASP.NET CORE MVC 框架中定義了一個 IControllerModelConvention 接口,咱們能夠實現該接口在運行時爲 Action 附加一個 Route 模型。在項目中新建 DashedRoutingConvention 類文件,代碼以下:html
public class DashedRoutingConvention : IControllerModelConvention { public void Apply(ControllerModel controller) { var hasRouteAttributes = controller.Selectors.Any(selector => selector.AttributeRouteModel != null); if (hasRouteAttributes) { // This controller manually defined some routes, so treat this // as an override and not apply the convention here. return; } foreach (var controllerAction in controller.Actions) { foreach (var selector in controllerAction.Selectors.Where(x => x.AttributeRouteModel == null)) { var parts = new List<string>(); foreach (var attr in controller.Attributes) { if (attr is AreaAttribute area) { parts.Add(area.RouteValue); } } if ( parts.Count == 0 && controller.ControllerName == "Home" && controllerAction.ActionName == "Index" ) { continue; } parts.Add(PascalToKebabCase(controller.ControllerName)); if (controllerAction.ActionName != "Index") { parts.Add(PascalToKebabCase(controllerAction.ActionName)); } selector.AttributeRouteModel = new AttributeRouteModel { Template = string.Join("/", parts) }; } } } private static string PascalToKebabCase(string value) { if (string.IsNullOrEmpty(value)) { return value; } return Regex.Replace( value, "(?<!^)([A-Z][a-z]|(?<=[a-z])[A-Z])", "-$1", RegexOptions.Compiled) .Trim() .ToLower(); } }
以後,將 DashedRoutingConvention 在 Startup.cs 中註冊。c#
public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(options => options.Conventions.Add(new DashedRoutingConvention())); }
至此,所有代碼完畢。 Notices:mvc