在使用 ModelBinder 之前更改文化
Posted
技术标签:
【中文标题】在使用 ModelBinder 之前更改文化【英文标题】:Change culture before ModelBinder is used 【发布时间】:2012-11-18 22:28:49 【问题描述】:我想创建一个不同语言的网站。我已经读到我可以创建一个ActionFilter,但我有一个小问题:
我必须创建一个自定义 ModelBinder 才能使用英语和德语数字格式(123,456,789.1
与 123.456.789,1
)
public class DecimalModelBinder : DefaultModelBinder
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
string key = bindingContext.ModelName;
var v = ((string[])bindingContext.ValueProvider.GetValue(key).RawValue)[0];
float outPut;
if (float.TryParse(v, NumberStyles.Number, System.Globalization.CultureInfo.CurrentCulture, out outPut))
return outPut;
return base.BindModel(controllerContext, bindingContext);
此 ModelBinder 使用当前区域性来决定使用哪种格式。 但不幸的是,ModelBinder 是在 ActionFilter 改变文化之前使用的。
如何在 ModelBinder 激活之前更改文化?
【问题讨论】:
【参考方案1】:您可以实现 IHttpModule 并在 BeginRequest 中设置文化,如 here 所示。
void context_BeginRequest(object sender, EventArgs e)
// eat the cookie (if any) and set the culture
if (HttpContext.Current.Request.Cookies["lang"] != null)
HttpCookie cookie = HttpContext.Current.Request.Cookies["lang"];
string lang = cookie.Value;
var culture = new System.Globalization.CultureInfo(lang);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
【讨论】:
它工作正常,非常感谢!但是我有一个问题:你知道吗,为什么每次请求都会执行 5 次代码? 我没有这种行为。能不能给((System.Web.HttpApplication)(sender)).Request.RawUrl加个watch看看请求是不是一样? @Christopher 代码在每个请求中执行一次(因此命名为 BeginRequest),因此页面可能有一个请求,样式表、图像或 javascript 文件可能还有 4 个请求。检查 Request.Url,这可能会有所帮助。【参考方案2】:我通常通过处理Global.asax.cs
中的PreRequestHandlerExecute
事件来设置CurrentCulture
和CurrentUICulture
(您也可以按照barry 的建议在IHttpModule
中处理此事件)。
关键是在模型绑定发生之前发生的事件中执行此操作。在此之前还发生了其他一些事件,您可以利用这些事件。
查看HttpApplication Class 以获取有关可用事件及其引发顺序的信息。
public class MvcApplication : HttpApplication
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
var culture = new CultureInfo("en-GB"); // Get the culture name from the route values / request querystring / form / cookie
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
您也可以通过处理Controller
上的OnActionExecuting
事件来实现(您可能希望创建一个基本控制器并在那里执行此操作,然后让您的所有控制器都从该基本控制器继承)。
public class MyBaseController : Controller
protected override void OnActionExecuting(ActionExecutingContext filterContext)
var culture = new CultureInfo("en-GB"); // Get the culture name from the route values / request querystring / form / cookie
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
base.OnActionExecuting(filterContext);
public class MyController : MyBaseController
public ActionResult Index()
return View();
【讨论】:
-1:在调用模型绑定器之后调用 OnActionExecuting。所以 OnActionExecuting 为时已晚。【参考方案3】:IAuthorizationFilter
的实例在模型绑定之前执行,从而允许您设置所需的文化
【讨论】:
以上是关于在使用 ModelBinder 之前更改文化的主要内容,如果未能解决你的问题,请参考以下文章