转换自定义操作筛选器以供Web API使用?

我发现了一个非常好的动作filter,它将逗号分隔的参数转换为generics类型列表: http : //stevescodingblog.co.uk/fun-with-action-filters/

我想使用它,但它不适用于ApiController,它完全忽略它。 有人可以帮助转换这个用于Web API吗?

[AttributeUsage(AttributeTargets.Method)] public class SplitStringAttribute : ActionFilterAttribute { public string Parameter { get; set; } public string Delimiter { get; set; } public SplitStringAttribute() { Delimiter = ","; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.ActionParameters.ContainsKey(this.Parameter)) { string value = null; var request = filterContext.RequestContext.HttpContext.Request; if (filterContext.RouteData.Values.ContainsKey(this.Parameter) && filterContext.RouteData.Values[this.Parameter] is string) { value = (string)filterContext.RouteData.Values[this.Parameter]; } else if (request[this.Parameter] is string) { value = request[this.Parameter] as string; } var listArgType = GetParameterEnumerableType(filterContext); if (listArgType != null && !string.IsNullOrWhiteSpace(value)) { string[] values = value.Split(Delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var listType = typeof(List).MakeGenericType(listArgType); dynamic list = Activator.CreateInstance(listType); foreach (var item in values) { try { dynamic convertedValue = TypeDescriptor.GetConverter(listArgType).ConvertFromInvariantString(item); list.Add(convertedValue); } catch (Exception ex) { throw new ApplicationException(string.Format("Could not convert split string value to '{0}'", listArgType.FullName), ex); } } filterContext.ActionParameters[this.Parameter] = list; } } base.OnActionExecuting(filterContext); } private Type GetParameterEnumerableType(ActionExecutingContext filterContext) { var param = filterContext.ActionParameters[this.Parameter]; var paramType = param.GetType(); var interfaceType = paramType.GetInterface(typeof(IEnumerable).FullName); Type listArgType = null; if (interfaceType != null) { var genericParams = interfaceType.GetGenericArguments(); if (genericParams.Length == 1) { listArgType = genericParams[0]; } } return listArgType; } } 

您为ActionFilterAttribute使用了什么名称空间? 对于Web API,您需要使用System.Web.Http.Filters命名空间而不是System.Web.Mvc

编辑

这是一个粗略的转换,没有经过全面测试。

SplitStringAttribute

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Net.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; namespace StackOverflowSplitStringAttribute.Infrastructure.Attributes { [AttributeUsage(AttributeTargets.Method)] public class SplitStringAttribute : ActionFilterAttribute { public string Parameter { get; set; } public string Delimiter { get; set; } public SplitStringAttribute() { Delimiter = ","; } public override void OnActionExecuting(HttpActionContext filterContext) { if (filterContext.ActionArguments.ContainsKey(Parameter)) { var qs = filterContext.Request.RequestUri.ParseQueryString(); if (qs.HasKeys()) { var value = qs[Parameter]; var listArgType = GetParameterEnumerableType(filterContext); if (listArgType != null && !string.IsNullOrWhiteSpace(value)) { string[] values = value.Split(Delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var listType = typeof(List<>).MakeGenericType(listArgType); dynamic list = Activator.CreateInstance(listType); foreach (var item in values) { try { dynamic convertedValue = TypeDescriptor.GetConverter(listArgType).ConvertFromInvariantString(item); list.Add(convertedValue); } catch (Exception ex) { throw new ApplicationException(string.Format("Could not convert split string value to '{0}'", listArgType.FullName), ex); } } filterContext.ActionArguments[Parameter] = list; } } } base.OnActionExecuting(filterContext); } private Type GetParameterEnumerableType(HttpActionContext filterContext) { var param = filterContext.ActionArguments[Parameter]; var paramType = param.GetType(); var interfaceType = paramType.GetInterface(typeof(IEnumerable<>).FullName); Type listArgType = null; if (interfaceType != null) { var genericParams = interfaceType.GetGenericArguments(); if (genericParams.Length == 1) { listArgType = genericParams[0]; } } return listArgType; } } } 

CsvController

 using System.Web.Http; using System.Collections.Generic; using StackOverflowSplitStringAttribute.Infrastructure.Attributes; namespace StackOverflowSplitStringAttribute.Controllers { public class CsvController : ApiController { // GET /api/values [SplitString(Parameter = "data")] public IEnumerable Get(IEnumerable data) { return data; } } } 

示例请求

 http://localhost:52595/api/csv?data=this,is,a,test,joe 

这是另一种方式:

 public class ConvertCommaDelimitedList : CollectionModelBinder { public override bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { var _queryName = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query)[bindingContext.ModelName]; List _model = new List(); if (!String.IsNullOrEmpty(_queryName)) _model = _queryName.Split(',').ToList(); var converter = TypeDescriptor.GetConverter(typeof(T)); if (converter != null) bindingContext.Model = _model.ConvertAll(m => (T)converter.ConvertFromString(m)); else bindingContext.Model = _model; return true; } } 

并在ApiController ActionMethod中列出您的参数:

 [ModelBinder(typeof(ConvertCommaDelimitedList))] List StudentIds = null) 

其中StudentIds是查询字符串参数( &StudentIds=1,2,4