ASP.NET MVC实现Localize站点的Action Filter

时间:2022-11-01 04:12:15

      ASP.NET MVC实现Localize站点的 Action Filter

       假设你已经了解Action Filter(see ASP.NET MVC的官方Understanding Action Filters),下面实现了Localize的Filter,直接看代码:

    1 using System.Globalization;
    2 using System.Web.Mvc;
    3 
    4 namespace LocalizedMVC.Controllers
    5 {
    6     public class SetCultureAttribute : FilterAttribute, IActionFilter
    7     {
    8         #region Enums
    9 
   10         /// <summary>
   11         /// Represents the location the culture code can be found
   12         /// </summary>
   13         public enum CultureLocation
   14         {
   15             /// <summary>
   16             /// This option should never be used.
   17             /// </summary>
   18             None = 0,
   19             /// <summary>
   20             /// Use when the culture code is saved in a cookie.
   21             /// When using be sure to specify the CookieName property.
   22             /// </summary>
   23             Cookie = 1,
   24             /// <summary>
   25             /// Use when the culture code is specified in the query string.
   26             /// When using be sure to specify the QueryStringParamName property.
   27             /// </summary>
   28             QueryString = 2,
   29             /// <summary>
   30             /// Use when the culture code is saved in session state.
   31             /// When using be sure to specify the SessionParamName property.
   32             /// </summary>
   33             Session = 4,
   34             /// <summary>
   35             /// Use when the culture code is specified in the URL.
   36             /// This assume a format of "{language}/{country}".
   37             /// When using be sure to specify the CountryActionParamName and
   38             /// LanguageActionParamName properties.
   39             /// </summary>
   40             URL = 16
   41         }
   42 
   43         #endregion Enums
   44 
   45         #region Properties
   46 
   47         /// <summary>
   48         /// The name of the cookie containing the culture code.  Specify this value when CultureStore is set to Cookie.
   49         /// </summary>
   50         public string CookieName { get; set; }
   51         /// <summary>
   52         /// The name of the action parameter containing the country code.  Specify this value when CultureStore is set to URL.
   53         /// </summary>
   54         public string CountryActionParamName { get; set; }
   55         /// <summary>
   56         /// The CultureLocation where the culture code is to be read from.  This is required to be set.
   57         /// </summary>
   58         public CultureLocation CultureStore { get; set; }
   59         /// <summary>
   60         /// The name of the action parameter containing the language code.  Specify this value when CultureStore is set to URL.
   61         /// </summary>
   62         public string LanguageActionParamName { get; set; }
   63         /// <summary>
   64         /// The name of the query string parameter containing the country code.  Specify this value when CultureStore is set to QueryString.
   65         /// </summary>
   66         public string QueryStringParamName { get; set; }
   67         /// <summary>
   68         /// The name of the session parameter containing the country code.  Specify this value when CultureStore is set to Session.
   69         /// </summary>
   70         public string SessionParamName { get; set; }
   71 
   72         #endregion Properties
   73 
   74         #region IActionFilter implementation
   75 
   76         public void OnActionExecuted(ActionExecutedContext filterContext)
   77         {
   78 
   79         }
   80 
   81         public void OnActionExecuting(ActionExecutingContext filterContext)
   82         {
   83             if (CultureStore == CultureLocation.None)
   84                 return;
   85 
   86             string cultureCode = GetCultureCode(filterContext);
   87 
   88             //now that we've collected the culture code, set the culture for the thread
   89             if (!string.IsNullOrEmpty(cultureCode))
   90             {
   91                 try
   92                 {
   93                     CultureInfo culture = new CultureInfo(cultureCode);
   94                     System.Threading.Thread.CurrentThread.CurrentCulture = culture;
   95                     System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
   96                 }
   97                 catch
   98                 {
   99                     //TODO: Handle error?  Really, what can we do besides log it?
  100                 }
  101             }
  102         }
  103 
  104         #endregion IActionFilter implementation
  105 
  106         protected string GetCultureCode(ActionExecutingContext filterContext)
  107         {
  108             //Everything but CultureLocation.URL requires a valid HttpContext
  109             if (CultureStore != CultureLocation.URL)
  110             {
  111                 if (filterContext.RequestContext.HttpContext == null)
  112                     return string.Empty;
  113             }
  114 
  115             string cultureCode = string.Empty;
  116 
  117             if (CultureStore == CultureLocation.Cookie)
  118             {
  119                 if (filterContext.RequestContext.HttpContext.Request.Cookies[CookieName] != null
  120                     && filterContext.RequestContext.HttpContext.Request.Cookies[CookieName].Value != string.Empty)
  121                 {
  122                     cultureCode = filterContext.RequestContext.HttpContext.Request.Cookies[CookieName].Value;
  123                 }
  124 
  125                 return cultureCode;
  126             }
  127 
  128             if (CultureStore == CultureLocation.QueryString)
  129             {
  130                 cultureCode = filterContext.RequestContext.HttpContext.Request[QueryStringParamName];
  131                 return cultureCode ?? string.Empty;
  132             }
  133 
  134             if (CultureStore == CultureLocation.Session)
  135             {
  136                 if (filterContext.RequestContext.HttpContext.Session[SessionParamName] != null
  137                     && filterContext.RequestContext.HttpContext.Session[SessionParamName].ToString() != string.Empty)
  138                 {
  139                     cultureCode = filterContext.RequestContext.HttpContext.Session[SessionParamName].ToString();
  140                 }
  141 
  142                 return cultureCode;
  143             }
  144 
  145             //if URL it is expected the URL path will contain the culture
  146             if (CultureStore == CultureLocation.URL)
  147             {
  148                 if (filterContext.ActionParameters[LanguageActionParamName] != null && filterContext.ActionParameters[CountryActionParamName] != null
  149                     && filterContext.ActionParameters[LanguageActionParamName].ToString() != string.Empty && filterContext.ActionParameters[CountryActionParamName].ToString() != string.Empty
  150                     )
  151                 {
  152                     string language = filterContext.ActionParameters[LanguageActionParamName].ToString();
  153                     string country = filterContext.ActionParameters[CountryActionParamName].ToString();
  154                     cultureCode = language + "-" + country;
  155                 }
  156 
  157                 return cultureCode;
  158             }
  159 
  160             return cultureCode ?? string.Empty;
  161         }
  162     }
  163 }

 

     如何使用呢?

[HandleError]
[SetCulture(CultureStore = SetCultureAttribute.CultureLocation.QueryString, QueryStringParamName = "culture")]
public class HomeController : Controller
{ ... actions ... }

QueryString 的方式:
http://localhost/?culture=en-GB"

 

如果存在session中你可以修改属性为那些东东为:

[SetCulture(CultureStore = SetCultureAttribute.CultureLocation.Session, SessionParamName = "culture")]

如果存在cookie中你可以修改属性为: 

[SetCulture(CultureStore = SetCultureAttribute.CultureLocation.Cookie, CookieName = "culture")]

如果想通用URL标准你期待的国家和语言时,那可能你的route需要认同.当请求http://localhost/en/us/home/about" 这个URL时...看下面的代码,

routes.MapRoute(
    "Default",                                              // Route name
    "{language}/{country}/{controller}/{action}/{id}",                           // URL with parameters

    new { controller = "Home", action = "Index", id = "", language = "en", country = "US" }  // Parameter defaults
);

更新路由后,修改SetCulture的属性为:

[SetCulture(CultureStore = SetCultureAttribute.CultureLocation.URL, CountryActionParamName = "country", LanguageActionParamName = "language")]

 

等等....

 

culture代码在当前的线程与UI通过这种方式设置:

CultureInfo culture = new CultureInfo (cultureCode);
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;

 

作者:PetterLiu  blog: http://wintersun.cnblogs.com  参考:source