Измените культуру до использования ModelBinder

Я хочу создать сайт на разных языках. Я уже читал, что могу создать 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 станет активным?


person Christopher    schedule 18.11.2012    source источник


Ответы (3)


Вы можете реализовать IHttpModule и установить культуру в BeginRequest, как показано здесь.

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;
    }
}
person barry    schedule 18.11.2012
comment
Это работает, спасибо вам большое! Но у меня один вопрос: знаете ли вы, почему код выполняется 5 раз за запрос? - person Christopher; 08.12.2012
comment
Я не понимаю такого поведения. Можете ли вы добавить часы в ((System.Web.HttpApplication) (sender)). Request.RawUrl и посмотреть, совпадают ли запросы? - person barry; 08.12.2012
comment
@Christopher Код выполняется один раз за запрос (отсюда и название BeginRequest), поэтому, возможно, есть один запрос для страницы и еще 4 для таблиц стилей, изображений или файлов JavaScript. Проверьте Request.Url, который может пролить свет. - person Alex York; 01.10.2013

Я обычно устанавливаю CurrentCulture и CurrentUICulture, обрабатывая событие PreRequestHandlerExecute в Global.asax.cs (вы также можете обработать это событие в IHttpModule, как предлагает Барри).

Дело в том, чтобы сделать это в событии, которое происходит до того, как произойдет привязка модели. Есть несколько других событий, которые происходят перед этим, которые вы можете использовать.

Просмотрите класс HttpApplication для получения информации о доступных событиях и порядке, в котором они подняты.

    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;
        }
    }

Вы также можете сделать это, обработав событие OnActionExecuting на вашем Controller (вы, вероятно, захотите создать базовый контроллер и сделать это там, а затем унаследовать все ваши контроллеры от этого базового контроллера).

    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();
        }
    }
person jfiskvik    schedule 21.11.2012
comment
-1: OnActionExecuting вызывается ПОСЛЕ вызова связывания модели. Так что OnActionExecuting слишком поздно. - person Rookian; 11.12.2013

Экземпляры IAuthorizationFilter выполняются перед привязкой модели, что позволяет вам установить необходимые культуры

person janv8000    schedule 15.01.2015