使用整数数组和操作的Web Api路由

时间:2014-09-26 05:03:49

标签: c# .net asp.net-web-api asp.net-web-api-routing

这个问题让我疯狂。

我有一个get方法,它使用自定义ModelBinder获取ID数组(我可以调用http://xckvjl.com/api/results/1,23,34),

我想介绍一下Get on actions。 (这样我可以称为http://alskjdfasl.com/api/results/latest

我有以下网络API路由。

config.Routes.MapHttpRoute("DefaultApi", "{controller}/{id}", new { id = RouteParameter.Optional });

config.Routes.MapHttpRoute("ApiWithAction", "{controller}/{action}");

我试过(请注意我在使用我的自定义模型装订器)

config.Routes.MapHttpRoute("DefaultApi", "{controller}/{id}", new { id = RouteParameter.Optional }, new {id = @"\d+" });

您可以使用此示例重现此错误:

public class TestController: ApiController {

          [HttpGet]
           public virtual IHttpActionResult Get([ModelBinder(typeof(CommaDelimitedCollectionModelBinder))]IEnumerable<int> id = null )
        { }

          [HttpGet]
           public virtual IHttpActionResult Latest( )
        { }

}

 public class CommaDelimitedCollectionModelBinder : IModelBinder
    {
        public bool BindModel(HttpActionContext actionContext,
            ModelBindingContext bindingContext)
        {
            var key = bindingContext.ModelName;
            var val = bindingContext.ValueProvider.GetValue(key);

            if (val == null)
            {
                return false;
            }

            var s = val.AttemptedValue;
            if (s != null && s.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Length > 0)
            {
                var array = s.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select( n=>Convert.ToInt32(n)).ToArray();
                Type type = bindingContext.ModelType.GetGenericArguments().First();

                var typeValue = Array.CreateInstance(type, array.Length);
                array.CopyTo(typeValue, 0);

                bindingContext.Model = array;
            }
            else
            {
                bindingContext.Model = new[] { s };
            }

            return true;
        }
    }

如果我写作:

[HttpGet]
[Route("Tests/latest")]
 public virtual IHttpActionResult Latest( )
        { }

有效。但是,我想要全局级别路由。否则,对于每一个动作,我都必须写相同的内容。

请告知。

1 个答案:

答案 0 :(得分:0)

所以这里是dilimma:

使用此路线定义:

config.Routes.MapHttpRoute("DefaultApi", "{controller}/{id}", new { id = RouteParameter.Optional });

当您致电http://alskjdfasl.com/api/results/latest时,latest成为id的值,显然会抛出错误,因为字符串无法转换为int数组。

添加此路线定义

config.Routes.MapHttpRoute("ApiWithAction", "{controller}/{action}"); 

因为现在您要么必须处理订单或为您的其他行为定义路线,因此不会给您带来帮助。

如果不在单个级别声明路由,则唯一的其他选项是使模板不同或创建自己的路径约束来理解数组。

我会先给出这些镜头:

config.Routes.MapHttpRoute("ApiWithAction", "{controller}/{action}/{id}", new { id = RouteParameter.Optional });

// or if all your methods are called latest

config.Routes.MapHttpRoute("ApiWithAction", "{controller}/latest");

如果没有任何作用,我会说去属性路线。他们更清洁。