Глобализация MVC3: нужен глобальный фильтр перед привязкой модели - PullRequest
14 голосов
/ 26 августа 2011

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

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 Ответ

15 голосов
/ 26 августа 2011

Извлеките код, который определяет культуру, в отдельный компонент / класс.Затем создайте 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();
...