MVC数据注释层:set CurrentUICulture语句放在哪里?

发布于 2024-08-06 05:55:17 字数 1089 浏览 7 评论 0原文

我对 MVC 应用程序的本地化感到着迷。

我最近的一个问题之后,我遵循了这种方法:

  1. 语言存储在 Session["lang"] 中,
  2. 每个控制器都继承自我自己的 BaseController,它重写了 OnActionExecuting,并在此方法中读取 Session 并设置 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();
}

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

我尝试过将 CurrentCulture 和 CurrentUiCulture 放入 Application_* (例如 Application_AcquireRequestState 或 Application_PreRequestHandlerExecute)似乎没有效果......

I am getting crazy with the localization of an MVC application.

After a recent question of mine I have followed this approach:

  1. The language is stored in Session["lang"]
  2. Each controller inherits from my own BaseController, which overrides OnActionExecuting, and in this method reads the Session and sets CurrentCulture and CurrentUICulture

This works great, until the Data Annotation Layer comes in. It seems like it gets called BEFORE the action itself is executed, and therefore it always gets the error messages in the default language!

The fields declarations go like this:

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

So, is there any reasonable place where I can put the call?

I initialize the Data Annotation Model Binder in my Controller constructor.

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

So, since Session is always null in the controller's constructor, and the action override is called AFTER the data annotation has validated the fields, where can I possibly set the CurrentCulture and CurrentUICulture to get localized errors?

I tried putting the CurrentCulture and CurrentUiCulture in Application_* (e.g. Application_AcquireRequestState or Application_PreRequestHandlerExecute) seems to have no effect...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

错々过的事 2024-08-13 05:55:18

由于区域性是全局用户设置,因此我在 Global.asax.cs 文件的 Application_BeginRequest 方法中使用它。

它为我完成了工作(使用cookie),但会话也在那里可用。

编辑:

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

会话在 PreRequesthandlerExecute 中可用。

问题是,您的代码正在为每个进入服务器的请求执行,并且某些请求(例如 WebResourxe.axd 的请求)不会利用
会话(因为处理程序没有实现 IRequireSessionState)。因此,将您的代码更改为仅在该请求有权访问会话时才访问会话。

更改你的代码来执行此操作:

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

无论如何,不​​确定它是否适用于 mvc

As the culture is a global user setting, I am using it in the global.asax.cs file in the Application_BeginRequest method.

It does the work for me (using cookies) but the Session is also available there.

EDIT:

/by Brock Allen:
http://www.velocityreviews.com/forums/t282576-aspnet-20-session-availability-in-globalasax.html/

Session is available in PreRequesthandlerExecute.

The problem is that your code is being executed for every request into the server, and some requests (like ones for WebResourxe.axd) don't utlilize
Session (because the handler doesn't implement IRequireSessionState). So change your code to only access Session if that request has access to it.

Change your code to do this:

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

Anyway, not sure if it works with mvc

拿命拼未来 2024-08-13 05:55:18

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

检查 Resource.resx 属性,找到 Build Action 并将其设置为 Embedded Resource
同时将 Custom Tool 更改为 PublicResXFileCodeGenerator

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

我已经测试了一个迷你解决方案并且工作完美。
如果您还有更多问题,我可以将示例发送给您。

After reading your question more carefully, I think that your problem is more in the way the resources are compiled.

Check in the Resource.resx properties, find Build Action and set it to Embedded Resource
Also change Custom Tool to PublicResXFileCodeGenerator

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

I have tested a mini solution and works perfectly.
If you have more problem, I can send the example to you.

泪冰清 2024-08-13 05:55:18

您可以使用的另一种方法是将 lang 放入 URL 中,这样做的好处是:

  • 站点由不同语言的搜索引擎抓取
  • 用户可以使用所选语言向朋友发送 URL

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

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

请参阅这个问题了解如何实现它的更多信息

Another approach you can use is to put the lang in the URL, with this benefits:

  • The site is spidered by search engines in different languages
  • The user can send a URL to a friend in the selected language

To do this, use the Application_BeginRequest method in 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

See this question for more info on how to implement it

瞄了个咪的 2024-08-13 05:55:18

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

The OP posted the final solution as the following, thanks to the accepted answer by twk:

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);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文