代码之家  ›  专栏  ›  技术社区  ›  Palantir

MVC数据注释层:将set-CurrentUICulture语句放在何处?

  •  3
  • Palantir  · 技术社区  · 16 年前

    我对MVC应用程序的本地化越来越着迷。

    之后 a recent question of mine 我采取了这种做法:

    1. 每个控制器都继承自我自己的BaseController,它重写OnActionExecuting,并在此方法中读取会话并设置CurrentCulture和CurrentUICulture

    这非常有效,直到数据注释层出现。它似乎是在执行操作之前被调用的,因此它总是以默认语言获取错误消息!

    字段声明如下所示:

    [Required(ErrorMessageResourceName = "validazioneRichiesto", ErrorMessageResourceType = typeof(Resources.Resources))]
    public string nome { get; set; }
    

    我在控制器构造函数中初始化数据注释模型绑定器。

    public CardController() : base() {
        ModelBinders.Binders.DefaultBinder =
        new Microsoft.Web.Mvc.DataAnnotations.DataAnnotationsModelBinder();
    }
    

    因此,由于会话在控制器的构造函数中始终为null,并且在数据注释验证字段后调用操作重写, 在哪里可以设置CurrentCulture和CurrentUICulture以获取本地化错误?

    4 回复  |  直到 8 年前
        1
  •  2
  •   twk    16 年前

    由于区域性是一个全局用户设置,因此我在应用程序_BeginRequest方法的global.asax.cs文件中使用它。

    它为我做的工作(使用cookies),但该会话也可以在那里使用。

    编辑:

    /布罗克·艾伦: http://www.velocityreviews.com/forums/t282576-aspnet-20-session-availability-in-globalasax.html/

    会话在PreRequesthandlerExecute中可用。

    问题是,您的代码正在为服务器中的每个请求执行,而有些请求(如webresourcxe.axd请求)没有utlilize 会话(因为处理程序未实现IRequireSessionState)。所以,如果请求有权访问会话,请将代码更改为仅访问会话。

    更改代码以执行此操作:

    protected void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
    {
        if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
            SetCulture();    
    }
    

    无论如何,不确定它是否与mvc一起工作

        2
  •  1
  •   Eduardo Molteni    16 年前

    在更仔细地阅读了您的问题之后,我认为您的问题更多地在于资源的编译方式。

    Resource.resx 属性,查找 Build Action 并将其设置为 Embedded Resource 也改变 Custom Tool PublicResXFileCodeGenerator

    alt text http://img208.imageshack.us/img208/2126/captuream.png

    我已经测试了一个迷你解决方案,效果非常好。

        3
  •  0
  •   Community Mohan Dere    8 年前

    您可以使用的另一种方法是将lang放在URL中,具有以下好处:

    • 该网站由不同语言的搜索引擎提供
    • 用户可以用所选语言向朋友发送URL

    要执行此操作,请使用 Application_BeginRequest 方法 Global.asax

    Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
        Dim lang As String
        If HttpContext.Current.Request.Path.Contains("/en/") Then
            lang = "en"
        Else
            lang = "es"
        End If
        Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang)
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(lang)
    End Sub
    

    看见 this question 有关如何实现它的更多信息

        4
  •  0
  •   rene    11 年前

    由于twk接受了答案,OP发布了以下最终解决方案:

    void Application_PreRequestHandlerExecute(object sender, EventArgs e) {
      if (Context.Handler is IRequiresSessionState || 
          Context.Handler is IReadOnlySessionState) {
        if (Session["lang"] == null) {
          Session["lang"] = "it";
        }
    
        if (Request.QueryString["lang"] == "it" || Request.QueryString["lang"] == "en") {
          Session["lang"] = Request.QueryString["lang"];
        }
    
        string lang1 = Session["lang"].ToString();
        string lang2 = Session["lang"].ToString().ToUpper();
    
        if (lang2 == "EN")
          lang2 = "GB";
    
        System.Threading.Thread.CurrentThread.CurrentCulture = 
            System.Globalization.CultureInfo.CreateSpecificCulture(lang1 + "-" + lang2);
        System.Threading.Thread.CurrentThread.CurrentUICulture = 
            System.Globalization.CultureInfo.CreateSpecificCulture(lang1 + "-" + lang2);
      }
    }