我想为我的用户提供虚荣网址,例如:
www.foo.com/sergio
我需要创建什么样的路线?
想象一下,我有以下控制器和动作,如何将虚荣URL映射到该控制器?
public ActionResult Profile(string username) { var model = LoadProfile(username); return View(model); }
这是我尝试过的,会发生什么:
选项A:
每个URL都在此路由中捕获,这意味着我键入的每个URL都指向我的帐户控制器,而不是仅指向foo.com/ [USERNAME].不好.
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Profile","{username}",new { controller = "Account",action = "Profile",username = UrlParameter.Optional } ); routes.MapRoute( "Default",// Route name "{controller}/{action}/{id}",// URL with parameters new { controller = "Home",action = "Index",id = UrlParameter.Optional } // Parameter defaults ); }
选项B:
默认路由工作正常,但在尝试访问配置文件foo.com/[USERNAME时,我收到HTTP 404错误.
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default",id = UrlParameter.Optional } // Parameter defaults ); routes.MapRoute( "DentistProfile",username = UrlParameter.Optional } ); }
解决方法
一个解决方案可能是使用自定义路由约束,
public class VanityUrlContraint : IRouteConstraint { private static readonly string[] Controllers = Assembly.GetExecutingAssembly().GetTypes().Where(x => typeof(IController).IsAssignableFrom(x)) .Select(x => x.Name.ToLower().Replace("controller","")).ToArray(); public bool Match(HttpContextBase httpContext,Route route,string parameterName,RouteValueDictionary values,RouteDirection routeDirection) { return !Controllers.Contains(values[parameterName].ToString().ToLower()); } }
并用它作为
routes.MapRoute( name: "Profile",url: "{username}",defaults: new {controller = "Account",action = "Profile"},constraints: new { username = new VanityUrlContraint() } ); routes.MapRoute( name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home",id = UrlParameter.Optional } );
这种方法的缺点是,与现有控制器名称相同的用户名的配置文件视图将不起作用,例如在项目中存在“资产”,“位置”和“AssetController”,“LocationController”等用户名,“资产”的配置文件视图,“位置”将无法正常工作.
希望这可以帮助.