为 Web API 使用转换自定义操作过滤器? [英] Convert custom action filter for Web API use?

查看:16
本文介绍了为 Web API 使用转换自定义操作过滤器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了一个非常好的动作过滤器,可以将逗号分隔的参数转换为通用类型列表:http://stevescodingblog.co.uk/fun-with-action-filters/

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/

我想使用它,但它不适用于 ApiController,它完全忽略它.有人可以帮助将其转换为 Web API 使用吗?

I would like to use it but it will not work for an ApiController, it completely ignore it. Can someone help convert this for Web API use?

[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.

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.

编辑

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

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

示例请求

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

这篇关于为 Web API 使用转换自定义操作过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆