MVC3: требуется глобальный фильтр перед привязкой модели

В настоящее время у меня есть глобальный фильтр с именем GlobalizationFilter, который проверяет значения маршрута, куки и заголовок браузера для определения правильных настроек культуры для запроса:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    // determine cultureInfo
    Thread.CurrentThread.CurrentCulture = cultureInfo;
    Thread.CurrentThread.CurrentUICulture = cultureInfo;
}

Все работает, но процесс привязки модели, по-видимому, возникает перед глобальными фильтрами, поэтому привязка модели не учитывает настройки культуры.

Это приводит к проблемам с интерпретацией двойных значений, значений DateTime и т.д.

Я мог бы переместить код обнаружения культуры в другие места, но мне не нравятся мои варианты:

  • Приложение BeginRequest событие. В этот момент маршрутизации не произошло, поэтому мне придется вручную вытащить маркер культуры /en-US/ из URL-адреса. Это неприемлемо.

  • Контроллер Initialize(). Это заставит меня написать базовый класс для всех моих контроллеров и наследовать от него существующие контроллеры. Мне это не нравится, но я выберу это решение, если ничего лучше не придумает.

В идеале, я хочу найти способ ввода моего кода между событиями "завершение маршрутизации" и "запуск привязки к модели", но я ничего не нашел в MSDN/Google.

Или может быть какой-то другой способ обработки MVC3-глобализации, о которой я не знаю?

Заранее благодарим за любой вклад.

Ответы

Ответ 1

Извлеките код, который определяет культуру в отдельный компонент/класс. Затем создайте ModelBinder, который вытекает из DefaultModelBinder, который использует класс для установки культуры перед вызовом BindModel

public class CultureAwareModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        /* code that determines the culture */
        var cultureInfo = CultureHelper.GetCulture(controllerContext.HttpContext);

        //set current thread culture
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Thread.CurrentThread.CurrentUICulture = cultureInfo;

        return base.BindModel(controllerContext, bindingContext);
    }
}

а затем зарегистрировать его для приложения (в Application_Start)

// register our own model binder as the default
ModelBinders.Binders.DefaultBinder = new CultureAwareModelBinder();