web-dev-qa-db-ja.com

多言語ASP.NET MVC Webアプリケーション用にCurrentCultureを設定するのに最適な場所

多言語ASP.NET MVC 3 Webアプリケーションの場合、Thread.CurrentThread.CurrentCultureおよびThread.CurrentThread.CurrentUICulture次のようにコントローラファクトリで:

public class MyControllerFactory : DefaultControllerFactory {

    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) {

        //Get the {language} parameter in the RouteData
        string UILanguage;
        if (requestContext.RouteData.Values["language"] == null)
            UILanguage = "tr";
        else
            UILanguage = requestContext.RouteData.Values["language"].ToString();

        //Get the culture info of the language code
        CultureInfo culture = CultureInfo.CreateSpecificCulture(UILanguage);
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;

        return base.GetControllerInstance(requestContext, controllerType);
    }

}

上記のコードはもう1年近く前です!だから、提案を募集します。

そして、これをGlobal.asaxファイルに次のように登録します。

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

これはうまく機能していますが、このタイプのアクションを実行するのに最適な方法であり、最適な場所であるかどうかはわかりません。

私はControllerFactoryの主な役割を掘り下げていませんが、ActionFilterAttributeと比較することはできません。

このタイプのアクションを行うのに最適な場所についてどう思いますか?

41
tugberk

このためにグローバルActionFilterを使用しましたが、最近、OnActionExecutingメソッドで現在のカルチャを設定するのが遅すぎる場合があることに気付きました。たとえば、POST要求の後のモデルがコントローラーに来ると、ASP.NET MVCはモデルのメタデータを作成します。アクションが実行される前に発生します。その結果、DisplayNameこの時点で、デフォルトのカルチャを使用して、属性値、およびその他のデータ注釈関連のものが処理されます。

最終的に、現在のカルチャをカスタムIControllerActivator実装に設定しましたが、これは魅力のように機能します。今日のように、リクエストライフサイクルの観点から見ると、カスタムコントローラーファクトリでこのロジックをホストすることはほぼ同じだと思います。グローバルActionFilterの使用よりもはるかに信頼性があります。

CultureAwareControllerActivator.cs

public class CultureAwareControllerActivator: IControllerActivator
{
    public IController Create(RequestContext requestContext, Type controllerType)
    {
        //Get the {language} parameter in the RouteData
        string language = requestContext.RouteData.Values["language"] == null ?
            "tr" : requestContext.RouteData.Values["language"].ToString();

        //Get the culture info of the language code
        CultureInfo culture = CultureInfo.GetCultureInfo(language);
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;

        return DependencyResolver.Current.GetService(controllerType) as IController;
    }
}

Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        ...
        ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new CultureAwareControllerActivator()));
    }
}
56
s.ermakovich

Anserが既に選択されていることを知っています。使用したオプションは、アプリケーションのOnBeginRequestイベントでスレッドの現在のカルチャを初期化するだけでした。これにより、すべてのリクエストで文化が発見されます

public void OnBeginRequest(object sender, EventArgs e)
{
   var culture = YourMethodForDiscoveringCulutreUsingCookie();
   System.Threading.Thread.CurrentThread.CurrentCulture = culture;
   System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
}
7
Agile Jedi

これを配置する別の場所は、GlobalFiltersコレクションに登録できるカスタムActionFilterのOnActionExecutingメソッドにそのコードを配置することです。

http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-global-action-filters.aspx

4
Paul Stovell

OnActionExecutingをオーバーライドする代わりに、ここでInitializeをオーバーライドできます。

protected override void Initialize(RequestContext requestContext)
{
        string culture = null;
        var request = requestContext.HttpContext.Request;
        string cultureName = null;

        // Attempt to read the culture cookie from Request
        HttpCookie cultureCookie = request.Cookies["_culture"];
        if (cultureCookie != null)
            cultureName = cultureCookie.Value;
        else
            cultureName = request.UserLanguages[0]; // obtain it from HTTP header AcceptLanguages

        // Validate culture name
        cultureName = CultureHelper.GetValidCulture(cultureName); // This is safe

        if (request.QueryString.AllKeys.Contains("culture"))
        {
            culture = request.QueryString["culture"];
        }
        else
        {
            culture = cultureName;
        }

        Uitlity.CurrentUICulture = culture;

        base.Initialize(requestContext);
    }
3
Hitendra

ControllerActivatorを使用しない場合は、BaseControllerクラスを使用して、それから非表示にすることができます。

public class BaseController : Controller
{
    public BaseController()
    {
          //Set CurrentCulture and CurrentUICulture of the thread
    }
}

public class HomeController: BaseController    
{
    [HttpGet]
    public ActionResult Index()
    {
        //..............................................
    }
}
0
Delyan