MVC 4:自定义路线和放大器; Html.Action不同步 [英] MVC 4: Custom Route & Html.Action out of synch

查看:176
本文介绍了MVC 4:自定义路线和放大器; Html.Action不同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有这个自定义路线,建立了基于URL文化的路由表,但是当我打电话Url.Action(...),它不会产生本地化URL。任何想法,我做错了什么?文化正在改变页面上,我能够确定选用何种语言的用户,但Url.Action不产生局部的URL。

这是自定义路线,从而改变路由表中的值(不知道这样做的这种标准方式):

 公共类CultureRoute:路线
{
    公共CultureRoute(字符串的URL,对象的默认值,对象约束上)
        :基地(网址,新MvcRouteHandler())
    {
        base.Defaults = CreateRouteValueDictionary(默认);
        base.Constraints = CreateRouteValueDictionary(约束上);
    }
    公众覆盖的RouteData GetRouteData(HttpContextBase的HttpContext)
    {
        VAR的RouteData = base.GetRouteData(HttpContext的);
        如果(的RouteData!= NULL)
        {
            VAR文化= routeData.Values​​ [文化]的ToString()。
            VAR饼干= httpContext.Request.Cookies [文化];
            VAR areEqual = FALSE;
            如果(饼干== NULL || cookie.Value ==||!(areEqual = string.Equals(文化,cookie.Value,StringComparison.OrdinalIgnoreCase)))
            {
                routeData.Values​​ [文化] =文化;
                httpContext.Response.Cookies.Add(新的HttpCookie(文化,文化));
            }
            否则,如果(!areEqual)
            {
                routeData.Values​​ [文化] = cookie.Value;
            }
            CultureHelper.SetCurrentCulture(培养);
        }
        返回的RouteData;
    }
    私有静态RouteValueDictionary CreateRouteValueDictionary(对象值)
    {
        VAR词典=值的IDictionary<字符串对象&gt ;;
        如果(字典!= NULL)
        {
            返回新RouteValueDictionary(字典);
        }
        其他
        {
            返回新RouteValueDictionary(值);
        }
    }
}

和这个辅助类来设置线程的文化:

 公共类CultureHelper
{
    公共静态无效SetCurrentCulture(串文化)
    {
        VAR信息= CultureInfo.CreateSpecificCulture(培养);
        Thread.CurrentThread.CurrentCulture =信息;
        Thread.CurrentThread.CurrentUICulture =信息;
    }
    公共静态字符串GetCurrentCulture(布尔ignoreRouteData = FALSE)
    {
        如果(!ignoreRouteData)
        {
            VAR的RouteData = HttpContext.Current.Request.RequestContext.RouteData;
            对象文化;
            如果(routeData.Values​​.TryGetValue(文化,文化出))
            {
                返回culture.ToString();
            }
        }
        VAR饼干= HttpContext.Current.Request.Cookies [文化];
        如果(饼干= NULL&放大器;!&安培;!cookie.Value = NULL)
        {
            返回cookie.Value;
        }
        返回GetThreadCulture();
    }
    公共静态字符串GetThreadCulture()
    {
        VAR文化= Thread.CurrentThread.CurrentCulture.Name;
        如果(culture.IndexOf(' - ')-1)〜
        {
            培养= culture.Substring(0,2);
        }
        返回文化;
    }
}

也是RouteConfig类,这是从在Global.asax打来电话,设置路由使用我的自定义路由类:

 公共类RouteConfig
{
    公共静态无效的RegisterRoutes(RouteCollection路线)
    {
        routes.IgnoreRoute({}资源个.axd / {*} PATHINFO);        routes.Add(部分,新CultureRoute(
            {文化} / {} cotroller /部分/ {}看法,
            新{文化=KA,控制器=家,行动=部分,认为=},
            新{文化=(か| EN)}));        routes.Add(默认,新CultureRoute(
            {文化} / {控制器} / {行动} / {ID}
            新{文化=KA,控制器=家,行动=指数,ID = UrlParameter.Optional},
            新{文化=(か| EN)}));
    }
}

但如果没有这个扩展方法,我不能够生成基于文化的路线,即Url.Action根据路由表中不生成URL中的自定义路由类创建:

 公共静态字符串措施2(这UrlHelper帮手,串动)
{
    VAR文化= CultureHelper.GetThreadCulture();
    返回helper.Action(动作,新的{文化=文化});
}


解决方案

这实际上是别的东西导致不正确的行为。我有一个扩展方法,这是产生动作切换语言,并将其修改的路由数据。

 公共静态字符串CultureRoute(这UrlHelper帮手,串文化=KA)
{
    VAR值= helper.RequestContext.RouteData.Values​​;
    。字符串actionName =值[行动]的ToString();
    如果(values​​.ContainsKey(文化))
    {
        值[文化] =文化;
    }
    其他
    {
        values​​.Add(文化,文化);
    }
    返回helper.Action(actionName,HttpContext.Current.Request.QueryString.ToRouteValues​​());
}

我改成了这一点,它的工作原理:

 公共静态字符串CultureRoute(这UrlHelper帮手,串文化=KA)
{
    VAR值= helper.RequestContext.RouteData.Values​​;
    。字符串actionName =值[行动]的ToString();
    返回helper.Action(actionName,新{文化=文化});
}

我并不需要重写 GetVirtualPath 方法来得到它的工作..我认为大部分的时间,我们可以用闪避路线类,只是重写 GetRouteData ,但想听听别人的想法......

So I have this custom route, which sets up the route table based on culture in the URL, but when I call Url.Action(...), it does not generate the localized URL. Any ideas what I'm doing wrong? The culture is changing on the page and I am able to determine what language user has selected, but Url.Action is not generating localized URL..

This is the custom route, which changes the route table values (not sure if this standard way of doing it):

public class CultureRoute : Route
{
    public CultureRoute(string url, object defaults, object contraints)
        : base(url, new MvcRouteHandler())
    {
        base.Defaults = CreateRouteValueDictionary(defaults);
        base.Constraints = CreateRouteValueDictionary(contraints);
    }
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var routeData = base.GetRouteData(httpContext);
        if (routeData != null)
        {
            var culture = routeData.Values["culture"].ToString();
            var cookie = httpContext.Request.Cookies["culture"];
            var areEqual = false;
            if (cookie == null || cookie.Value == "" || !(areEqual = string.Equals(culture, cookie.Value, StringComparison.OrdinalIgnoreCase)))
            {
                routeData.Values["culture"] = culture;
                httpContext.Response.Cookies.Add(new HttpCookie("culture", culture));                    
            }
            else if (!areEqual)
            {                    
                routeData.Values["culture"] = cookie.Value;
            }
            CultureHelper.SetCurrentCulture(culture);
        }            
        return routeData;
    }
    private static RouteValueDictionary CreateRouteValueDictionary(object values)
    {
        var dictionary = values as IDictionary<string, object>;
        if (dictionary != null)
        {
            return new RouteValueDictionary(dictionary);
        }
        else
        {
            return new RouteValueDictionary(values);
        }
    }  
}

and this helper class to set the thread culture:

public class CultureHelper
{
    public static void SetCurrentCulture(string culture)
    {
        var info = CultureInfo.CreateSpecificCulture(culture);
        Thread.CurrentThread.CurrentCulture = info;
        Thread.CurrentThread.CurrentUICulture = info;  
    }
    public static string GetCurrentCulture(bool ignoreRouteData = false)
    {
        if (!ignoreRouteData)
        {
            var routeData = HttpContext.Current.Request.RequestContext.RouteData;
            object culture;
            if (routeData.Values.TryGetValue("culture", out culture))
            {
                return culture.ToString();
            }
        }
        var cookie = HttpContext.Current.Request.Cookies["culture"];
        if (cookie != null && cookie.Value != null)
        {
            return cookie.Value;
        }
        return GetThreadCulture();
    }
    public static string GetThreadCulture()
    {
        var culture = Thread.CurrentThread.CurrentCulture.Name;
        if (culture.IndexOf('-') > -1)
        {
            culture = culture.Substring(0, 2);
        }
        return culture;
    }
}

and also the RouteConfig class, which is called from the Global.asax and sets up routes using my custom route class:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.Add("Partial", new CultureRoute(
            "{culture}/{cotroller}/partial/{view}",
            new { culture = "ka", controller = "home", action = "partial", view = "" },
            new { culture = "(ka|en)" }));

        routes.Add("Default", new CultureRoute(
            "{culture}/{controller}/{action}/{id}",
            new { culture = "ka", controller = "home", action = "index", id = UrlParameter.Optional },
            new { culture = "(ka|en)" }));
    }
}

but without this extension method, I am not able to generate culture based route i.e. Url.Action does not generate URL based on route table the custom route class creates:

public static string Action2(this UrlHelper helper, string action)
{ 
    var culture = CultureHelper.GetThreadCulture();
    return helper.Action(action, new { culture = culture });
}

解决方案

It was actually something else causing the incorrect behavior. I had an extension method that was generating actions to switch the language and it modified the route data.

public static string CultureRoute(this UrlHelper helper, string culture = "ka") 
{
    var values = helper.RequestContext.RouteData.Values;
    string actionName = values["action"].ToString();
    if (values.ContainsKey("culture"))
    {
        values["culture"] = culture;
    }
    else
    {
        values.Add("culture", culture);
    }
    return helper.Action(actionName, HttpContext.Current.Request.QueryString.ToRouteValues());
} 

I changed it to this and it works:

public static string CultureRoute(this UrlHelper helper, string culture = "ka") 
{
    var values = helper.RequestContext.RouteData.Values;
    string actionName = values["action"].ToString();
    return helper.Action(actionName, new { culture = culture });
}

I do not need to override GetVirtualPath method to get it to work.. I think most of the time we can get away with Route class and just overriding GetRouteData, but would like to hear what others think...

这篇关于MVC 4:自定义路线和放大器; Html.Action不同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆