在ASP.NET WEB API 2进行动态的APICONTROLLER层级组态
ASP.NET WEB AP 2进行APICONTROLLER层级的组态’是通过属性(Attribute)设置方式来为ApiControler加入静态设置。它无法在执行期间改变。
操作ICONTROLLERCONFIGURATION介面
方法为:
- public class JsonOnlyAttribute : Attribute, IControllerConfiguration
- {
- public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
- {
- controllerSettings.Formatters.Clear();
- controllerSettings.Formatters.Add(new JsonMediaTypeFormatter());
- }
- }
以上是仅提供JSON Formatter的范例,这样的好处是不用整个ASP.NET Web API 2项目都完全关闭XML Formatter,需要关闭时才关闭。
以下简述Filip文章以了解如何进行动态Controller组态。
CONTROLLER层级组态
一、新增一个延伸方法:
- public static class HttpConfigurationExtensions
- {
- /// <summary>
- /// 建立新HttpControllerSettings实体,并套用提供组态用户的变更。
- /// </summary>
- /// <param name="configuration">HttpConfiguration</param>
- /// <param name="settings">HttpControllerSettings</param>
- public static HttpConfiguration Copy(this HttpConfiguration configuration, Action<HttpControllerSettings> settings)
- {
- var controllerSettings = new HttpControllerSettings(configuration);
- settings(controllerSettings);
- // 调用HttpConfiguration私有构造函数(NonPublic)以建立调整用的HttpControllerSettings组态对象
- var constructor = typeof(HttpConfiguration).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,
- null,
- new[] { typeof(HttpConfiguration),
- typeof(HttpControllerSettings) },
- null);
- var instance = (HttpConfiguration)constructor.Invoke(new object[] { configuration, controllerSettings });
- return instance;
- }
- }
二、储存组态设置
- /// <summary>
- /// 储存Controller组态
- /// </summary>
- public class ControllerConfig
- {
- public static Dictionary<Type, Action<HttpControllerSettings>> Map = new Dictionary<Type, Action<HttpControllerSettings>>();
- }
三、由自定义IHttpControllerActivator调用HttpConfigurationExtensions方法
- public class PerControllerConfigActivator : IHttpControllerActivator
- {
- private static readonly DefaultHttpControllerActivator Default = new DefaultHttpControllerActivator();
- private readonly ConcurrentDictionary"Type, HttpConfiguration> _cache = new ConcurrentDictionary<Type, HttpConfiguration>();
- /// <summary>
- /// 建立 System.Web.Http.Controllers.IHttpController 对象。
- /// </summary>
- /// <param name="request">信息要求。</param>
- /// <param name="controllerDescriptor">HTTP 控制器描述元。</param>
- /// <param name="controllerType">控制器的类型。</param>
- /// <returns>IHttpController 对象</returns>
- public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
- {
- HttpConfiguration controllerConfig;
- // 检查每一个当下的Controller,是否有我们要组态的Controller类型
- // TryGetValue方法:尝试从 ConcurrentDictionary<TKey, TValue> 取得与指定之索引键相关联的值。
- if (_cache.TryGetValue(controllerType, out controllerConfig))
- {
- controllerDescriptor.Configuration = controllerConfig;
- }
- else if (ControllerConfig.Map.ContainsKey(controllerType))
- {
- // 调用 HttpConfigurationExtensions.Copy方法
- controllerDescriptorcontrollerDescriptor.Configuration = controllerDescriptor.Configuration.Copy(ControllerConfig.Map[controllerType]);
- // 为此Controller类型加入组态
- // TryAdd方法:如果它不存在于字典中,加入新的索引键加入字典
- _cache.TryAdd(controllerType, controllerDescriptor.Configuration);
- }
- // 建立新的IHttpcontroller
- var result = Default.Create(request, controllerDescriptor, controllerType);
- return result;
- }
- }
四、WebApiConfig进行动态组态
- // 自定义IHttpControllerActivator,叫呼新HttpConfigurationExtensions方法,
- config.Services.Replace(typeof(IHttpControllerActivator), new PerControllerConfigActivator());
- // 动态加入Controller层级设置
- ControllerConfig.Map.Add(typeof(TodoItems2Controller), settings =>
- {
- settings.Formatters.Clear();
- var jsonformatter = new JsonMediaTypeFormatter
- {
- SerializerSettings = { ContractResolver = new CamelCasePropertyNamesContractResolver() }
- };
- settings.Formatters.Add(jsonformatter);
- });
- ControllerConfig.Map.Add(typeof(TodoItemsController), settings =>
- {
- settings.Formatters.Clear();
- settings.Formatters.Add(new XmlMediaTypeFormatter());
- });
注解我都写在源程序之中了。注意,态动进行Controller层级组态与操作IControllerConfiguration介面的属性设置方式无法并存,原因也很简单,因为我们替换了自行操作的IHttpControllerActivator,它并不懂的如何解读操作IControllerConfiguration介面的属性。
如果只有少数Controller层级组态,那么ASP.NET Web API 2的IControllerConfiguration介面是个不错的方式。如果有大量的Controller层级组态需求,那么可以考虑Filip所提供的解决方案。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
