2012-06-08 24 views
21

私はジェネリック型のリストにカンマで区切られたパラメータを変換し、本当に素敵なアクションフィルタを見つけました。誰かがWeb APIを使用するためにこれを変換する手助けができますか?あなたがActionFilterAttributeのために使用されているどのような名前空間Web API用のカスタムアクションフィルタを使用しますか? <a href="http://stevescodingblog.co.uk/fun-with-action-filters/">http://stevescodingblog.co.uk/fun-with-action-filters/</a></p> <p>私はそれを使用したいと思いますが、それはApiControllerのために動作しません、それは完全にそれを無視:

[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; 
    } 
} 

答えて

26

? Web APIの場合、System.Web.Http.Filters名前空間を使用する必要があり、System.Web.Mvcを使用する必要はありません。

EDIT

はここでラフ変換、完全にテストされていないのです。

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<string> Get(IEnumerable<string> data) 
     { 
      return data; 
     } 
    } 
} 

ここ

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

私はそれが簡単ということでした希望をある

[ModelBinder(typeof(ConvertCommaDelimitedList<decimal>))] List<decimal> StudentIds = null) 

。私はちょうど試みたが、それはコンパイルされません。 filterContext.ActionParameters、filterContext.RequestContext、およびfilterContext.RouteDataは認識されません。 – TruMan1

+0

サンプルコード – Jonathan

+2

'System.Web.HttpFilters' - >' System.Web.Http.Filters' –

3

例要求がAでありますNotherの道:ApiController ActionMethodで

public class ConvertCommaDelimitedList<T> : CollectionModelBinder<T> 
{ 
    public override bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) 
    { 
     var _queryName = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query)[bindingContext.ModelName]; 
     List<string> _model = new List<string>(); 
     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; 
    } 
} 

し、リストあなたのparam:StudentIdsは、クエリ文字列のparam(&StudentIds=1,2,4

関連する問題

 関連する問題