Convert custom action filter for Web API use?

前端 未结 2 1163
青春惊慌失措
青春惊慌失措 2020-12-23 21:56

I found a really nice action filter that converts a comma-separated parameter to a generic type list: http://stevescodingblog.co.uk/fun-with-action-filters/

I would

相关标签:
2条回答
  • 2020-12-23 22:37

    Here is another way:

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

    And list your param in the ApiController ActionMethod:

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

    Where StudentIds is the querystring param (&StudentIds=1,2,4)

    0 讨论(0)
  • 2020-12-23 22:41

    What namespace are you using for ActionFilterAttribute? For Web API you need to be using System.Web.Http.Filters namespace and not System.Web.Mvc.

    EDIT

    Here's a rough conversion, not fully tested.

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

    Example request

    http://localhost:52595/api/csv?data=this,is,a,test,joe
    
    0 讨论(0)
提交回复
热议问题