我需要什么样的路线才能提供虚荣网址?

时间:2012-11-26 04:11:57

标签: asp.net-mvc-3 routes vanity-url

我想为我的用户提供虚荣网址,例如:

www.foo.com/sergio

我需要创建什么样的路线?

想象一下,我有以下控制器和操作,如何将虚荣URL映射到该控制器?

public ActionResult Profile(string username)
{
    var model = LoadProfile(username);
    return View(model);
}

以下是我尝试过的以及会发生什么:

选项A:

每个网址都会在此路由中被捕获,这意味着我输入的每个网址都会将我引导至帐户控制器,而不仅仅是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", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );

    routes.MapRoute(
        "DentistProfile",
        "{username}",
        new { controller = "Account", action = "Profile", username = UrlParameter.Optional }
    );
}

2 个答案:

答案 0 :(得分:1)

一个解决方案可能是使用自定义路由约束,

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", action = "Index", id = UrlParameter.Optional }
    );

这种方法的缺点是,与现有控制器名称相同的用户名的配置文件视图将不起作用,例如,如果有“资产”,“位置”和“AssetController”等用户名,“LocationController”存在于项目,配置文件视图中“资产”,“位置”将无效。

希望这会有所帮助。

答案 1 :(得分:0)

你试过了吗?

routes.MapRoute(
"YourRouteName",
"{username}",
new {controller="YourController", action="Profile", username=UrlParameter.Optional}
);

这应该陷入www.foo.com/{username}。请记住,路线会按照您添加的顺序进行检查,因此您可以添加

routes.MapRoute(
"default",
"{controller}/{action}/{input}",
new {controller="controller", action="action", input=UrlParameter.Optional}
);

首先保持"默认"行为。