隐式或会话值是否可以自动添加到ASP.NET MVC2中的Url.Action()中的RouteValues?

时间:2010-12-02 00:12:22

标签: asp.net asp.net-mvc

我们已经编写了大量代码,其中使用以下代码编写URL:

Url.Action("Index", "MyController", new {page=1})

我们的应用程序是一个多租户应用程序,我们的用户登录到他们的数据库。这意味着登录过程允许用户选择他们想要用于会话的数据库。我们没有在开头构建它,因此数据库名称是URL的一部分。这只是会议的一部分。

现在我们希望将数据库名称放在所有URL中,这样用户仍然可以使用浏览器URL创建书签,并正确访问该特定页面,而无需在登录期间选择正确的匹配数据库。从本质上讲,如果在ASP.NET MVC中有一种方法可以进行上述调用,那就太好了:

Url.Action("Index", "MyController", new {page=1, clientName=Identity.ClientName})

无需去任何地方并且手动进行。我们正在谈几千个地方......

这可行吗?

2 个答案:

答案 0 :(得分:0)

好吧,我认为现在无法做到这一点,我们需要编写自己的Url.Action,Html.ActionLink和Controller.Redirect实现,只需进行全局搜索和替换即可使用我们的版本。太糟糕了。

答案 1 :(得分:0)

我今天必须解决一个非常类似的问题。当我在寻找解决方案时,我找到了你的问题。我现在已经找到了一个解决方案,虽然它可能与您的项目不再相关,但对于偶然发现它的人来说可能会有所帮助。

我们可以通过向您的路由集合而不是vanilla MVC Route类添加Route类的自定义实现来解决此问题。所以像这样:

public class ClientNameRoute : Route
{
    public ClientNameRoute(string url, IRouteHandler routeHandler) : base (url, routeHandler) {}

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        values["clientName"] = Identity.ClientName;
        return base.GetVirtualPath(requestContext, values);
    }
}

然后,您需要制作一些扩展方法,以便更轻松地注册这些路由。例如:

public static RegionRoute MapClientNameRoute(this AreaRegistrationContext context, string name, string url, object defaults)
{
    if (context.Routes == null)
        throw new ArgumentNullException("context.Routes");

    if (url == null)
        throw new ArgumentNullException("url");

    if (context.Namespaces != null)
        context.Namespaces.ToArray();

    var route = new ClientNameRoute(url, new MvcRouteHandler())
                    {
                        Defaults = new RouteValueDictionary(defaults),
                        DataTokens = new RouteValueDictionary(),
                    };

    route.DataTokens["area"] = context.AreaName;

    var useNamespaceFallback = context.Namespaces == null || context.Namespaces.Count == 0;
    route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;

    if (!useNamespaceFallback)
        route.DataTokens["Namespaces"] = context.Namespaces.ToArray();

    context.Routes.Add(name, route);

    return route;
}

public static RegionRoute MapClientNameRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces)
{
    if (routes == null)
        throw new ArgumentNullException("routes");

    if (url == null)
        throw new ArgumentNullException("url");

    var route = new ClientNameRoute(url, new MvcRouteHandler())
    {
        Defaults = new RouteValueDictionary(defaults),
        DataTokens = new RouteValueDictionary()
    };

    if (namespaces != null && namespaces.Length > 0)
    {
        route.DataTokens["Namespaces"] = namespaces;
    }
    routes.Add(name, route);
    return route;
}