1

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

www.foo.com/sergio

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

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

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

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

选项 A:

每个 url 都在这条路由中被捕获,这意味着我输入的每个 URL 都将我引导到 Account 控制器,而不仅仅是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 }
    );
}
4

2 回答 2

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 }
    );

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

希望这可以帮助。

于 2012-11-30T08:07:49.267 回答
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}
);

首先要保持“默认”行为。

于 2012-11-27T18:09:44.193 回答