2012-06-08 6 views
21

Ben genel tür listesine virgülle ayrılmış parametre dönüştüren gerçekten güzel bir eylem filtresi bulundu. Birisi bunu Web API kullanımı için dönüştürmeye yardımcı olabilir mi?Web API kullanımı için özel eylem filtresini dönüştürün? <a href="http://stevescodingblog.co.uk/fun-with-action-filters/">http://stevescodingblog.co.uk/fun-with-action-filters/</a></p> <p>bunu kullanmak istiyorum ama bir ApiController için çalışmaz, tamamen görmezden:

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

cevap

26

Ne ad sen ActionFilterAttribute için kullanıyorsunuz? Web API için System.Web.Mvc değil System.Web.Http.Filters ad alanı kullanmanız gerekir.

DÜZENLEME

İşte kaba bir dönüşüm, tamamen test değil.

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

Burada

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

Ben kolay olsaydı olduğunu

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

. Az önce denedim ama derleme yapmıyor. FilterContext.ActionParameters, filterContext.RequestContext ve filterContext.RouteData tanımaz. – TruMan1

+0

Bazı örnek kod – Jonathan

+2

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

3

Örnek istek a, nother yol: ApiController ActionMethod içinde

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

Ve listelemek için param: StudentIds querystring param (&StudentIds=1,2,4)

İlgili konular