在 ASP.Net MVC 应用程序中设置文化
在 ASP.net MVC 应用程序中设置文化/UI 文化的最佳位置是什么
目前我有一个 CultureController 类,如下所示:
public class CultureController : Controller
{
public ActionResult SetSpanishCulture()
{
HttpContext.Session["culture"] = "es-ES";
return RedirectToAction("Index", "Home");
}
public ActionResult SetFrenchCulture()
{
HttpContext.Session["culture"] = "fr-FR";
return RedirectToAction("Index", "Home");
}
}
主页上每种语言的超链接带有如下链接:
<li><%= Html.ActionLink("French", "SetFrenchCulture", "Culture")%></li>
<li><%= Html.ActionLink("Spanish", "SetSpanishCulture", "Culture")%></li>
效果很好,但是我想有一个更合适的方法来做到这一点。
我正在使用以下 ActionFilter 阅读文化 http://www.iansuttle.com /blog/post/ASPNET-MVC-Action-Filter-for-Localized-Sites.aspx。我是一个 MVC 菜鸟,所以我不确定我是否将其设置在正确的位置。我不想在 web.config 级别执行此操作,它必须基于用户的选择。我也不想检查他们的 http 标头以从他们的浏览器设置中获取文化。
编辑:
澄清一下 - 我并不是想决定是否使用会话。我对这一点很满意。我想要解决的是,是否最好在具有要设置的每种文化的操作方法的文化控制器中执行此操作,或者 MVC 管道中是否有更好的位置来执行此操作?
What is the best place to set the Culture/UI Culture in an ASP.net MVC app
Currently I have a CultureController class which looks like this:
public class CultureController : Controller
{
public ActionResult SetSpanishCulture()
{
HttpContext.Session["culture"] = "es-ES";
return RedirectToAction("Index", "Home");
}
public ActionResult SetFrenchCulture()
{
HttpContext.Session["culture"] = "fr-FR";
return RedirectToAction("Index", "Home");
}
}
and a hyperlink for each language on the homepage with a link such as this:
<li><%= Html.ActionLink("French", "SetFrenchCulture", "Culture")%></li>
<li><%= Html.ActionLink("Spanish", "SetSpanishCulture", "Culture")%></li>
which works fine but I am thinking there is a more appropriate way to do this.
I am reading the Culture using the following ActionFilter
http://www.iansuttle.com/blog/post/ASPNET-MVC-Action-Filter-for-Localized-Sites.aspx. I am a bit of an MVC noob so am not confident I am setting this in the correct place. I don't want to do it at the web.config level, it has to be based on a user's choice. I also don't want to check their http-headers to get the culture from their browser settings.
Edit:
Just to be clear - I am not trying to decide whether to use session or not. I am happy with that bit. What I am trying to work out is if it is best to do this in a Culture controller that has an action method for each Culture to be set, or is there is a better place in the MVC pipeline to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我正在使用这个 本地化方法 并添加每当用户访问 example.com/xx-xx/ 时设置文化和语言的路由参数
示例:
我有一个执行实际文化/语言设置的过滤器:
要激活国际化属性,只需将其添加到您的类中:
现在每当访问者访问 http://example.com/de-DE/Home/Index 显示德语站点。
我希望这个答案能为您指明正确的方向。
我还制作了一个小型 MVC 5 示例项目,您可以在此处找到该项目,
只需访问 http:// {yourhost}:{port}/en-us/home/index 查看英语(美国)的当前日期,或将其更改为 http://{yourhost}:{port}/de-de/home/index德国之类的。
I'm using this localization method and added a route parameter that sets the culture and language whenever a user visits example.com/xx-xx/
Example:
I have a filter that does the actual culture/language setting:
To activate the Internationalization attribute, simply add it to your class:
Now whenever a visitor goes to http://example.com/de-DE/Home/Index the German site is displayed.
I hope this answers points you in the right direction.
I also made a small MVC 5 example project which you can find here
Just go to http://{yourhost}:{port}/en-us/home/index to see the current date in English (US), or change it to http://{yourhost}:{port}/de-de/home/index for German etcetera.
我知道这是一个老问题,但如果您真的希望将此与您的 ModelBinder 一起使用(相对于
DefaultModelBinder.ResourceClassKey = "MyResource";
以及数据注释中指示的资源视图模型类),控制器甚至ActionFilter
来不及设置区域性。区域性可以在
Application_AcquireRequestState
中设置,例如:EDIT
实际上,有一个更好的方法,使用自定义路由处理程序,它根据url,Alex Adamyan 在他的博客上完美描述了。
所需要做的就是重写
GetHttpHandler
方法并在那里设置区域性。I know this is an old question, but if you really would like to have this working with your ModelBinder (in respect to
DefaultModelBinder.ResourceClassKey = "MyResource";
as well as the resources indicated in the data annotations of the viewmodel classes), the controller or even anActionFilter
is too late to set the culture.The culture could be set in
Application_AcquireRequestState
, for example:EDIT
Actually there is a better way using a custom routehandler which sets the culture according to the url, perfectly described by Alex Adamyan on his blog.
All there is to do is to override the
GetHttpHandler
method and set the culture there.我会在控制器的初始化事件中这样做......
I would do it in the Initialize event of the controller like this...
由于它是按用户存储的设置,因此会话是存储信息的适当位置。
我会更改您的控制器以将区域性字符串作为参数,而不是为每种潜在的区域性使用不同的操作方法。添加到页面的链接很容易,并且您不需要在需要新区域性时重复编写相同的代码。
Being as it is a setting that is stored per-user, the session is an appropriate place to store the informtion.
I would change your controller to take the culture string as a parameter, rather than having a different action method for each potential culture. Adding a link to the page is easy, and you shouldn't need to write the same code repeatedly any time a new culture is required.
什么是最好的地方是你的问题。最好的地方是在 Controller.Initialize 方法。 MSDN 写道,它是在构造函数之后、操作方法之前调用的。与重写 OnActionExecuting 相反,将代码放在 Initialize 方法中可以让您受益于将类和属性上的所有自定义数据注释和属性进行本地化。
例如,我的本地化逻辑来自注入到我的自定义控制器的类。我可以访问这个对象,因为 Initialize 是在构造函数之后调用的。我可以进行线程的区域性分配,并且不会正确显示每个错误消息。
即使您的逻辑不像我提供的示例那样位于类内部,您也可以访问RequestContext 允许您拥有 URL 和 HttpContext 以及 RouteData
What is the best place is your question. The best place is inside the Controller.Initialize method. MSDN writes that it is called after the constructor and before the action method. In contrary of overriding OnActionExecuting, placing your code in the Initialize method allow you to benefit of having all custom data annotation and attribute on your classes and on your properties to be localized.
For example, my localization logic come from an class that is injected to my custom controller. I have access to this object since Initialize is called after the constructor. I can do the Thread's culture assignation and not having every error message displayed correctly.
Even if your logic is not inside a class like the example I provided, you have access to the RequestContext which allow you to have the URL and HttpContext and the RouteData which you can do basically any parsing possible.
如果使用子域(例如“pt.mydomain.com”)来设置葡萄牙语,则使用 Application_AcquireRequestState 将不起作用,因为后续缓存请求不会调用它。
为了解决这个问题,我建议这样的实现:
将 VaryByCustom 参数添加到 OutPutCache,如下所示:
在 global.asax.cs 中,使用函数调用从主机获取区域性:
将 GetCultureFromHost 函数添加到 global.asax.cs:
最后重写 GetVaryByCustomString(...) 以也使用此函数:
在非缓存调用上调用函数 Application_AcquireRequestState,这允许生成和缓存内容。在缓存调用上调用 GetVaryByCustomString 来检查缓存中的内容是否可用,在这种情况下,我们再次检查传入的主机域值,而不是仅依赖当前的区域性信息,该信息可能已针对新请求而更改(因为我们正在使用子域)。
If using Subdomains, for example like "pt.mydomain.com" to set portuguese for example, using Application_AcquireRequestState won't work, because it's not called on subsequent cache requests.
To solve this, I suggest an implementation like this:
Add the VaryByCustom parameter to the OutPutCache like this:
In global.asax.cs, get the culture from the host using a function call:
Add the GetCultureFromHost function to global.asax.cs:
And finally override the GetVaryByCustomString(...) to also use this function:
The function Application_AcquireRequestState is called on non-cached calls, which allows the content to get generated and cached. GetVaryByCustomString is called on cached calls to check if the content is available in cache, and in this case we examine the incoming host domain value, again, instead of relying on just the current culture info, which could have changed for the new request (because we are using subdomains).
1:创建一个自定义属性并重写方法,如下所示:
2:在App_Start中,找到FilterConfig.cs,添加此属性。 (这适用于整个应用程序)
就是这样!
如果您想为每个控制器/操作而不是整个应用程序定义区域性,您可以像这样使用此属性:
或者:
1: Create a custom attribute and override method like this:
2: In App_Start, find FilterConfig.cs, add this attribute. (this works for WHOLE application)
That's it !
If you want to define culture for each controller/action in stead of whole application, you can use this attribute like this:
Or: