我有一个现有的WebAPI 2项目,它有当前的路由:
config.Routes.MapHttpRoute
(
name: "API",
routeTemplate: "api/{controller}/{id}/{function}",
defaults: new { id = RouteParameter.Optional, function = RouteParameter.Optional }
);
控制器由通用基本控制器和每个"实体类型的派生控制器组成。实施 路线:
[GET] api/{entity}/ <- returns an overview list of entities
[GET] api/{entity}/{id} <- returns the full entity + details
[POST] api/{entity}/{id} <- saves the entity
[DEL] api/{entity}/{id} <- deletes the entity
[POST] api/{entity}/ <- creates a new entity
[POST] api/{entity}/{id}/{function} <- performs a function on an entity (eg. recalculate, send orders,..)
现在我想为我的basecontroller添加一个新方法,以便能够获得&#34; count&#34;获取概述清单。所以基本上
[GET] api/{entity}/count
我已将以下路由添加到webapi配置中:
config.Routes.MapHttpRoute
(
name: "count",
routeTemplate: "api/{controller}/", defaults: new { action = "count" }
);
并向我的控制器添加了一个方法:
[HttpGet]
public async Task<int> Count()
{
return 5;//just a fixed testvalue
}
如果我现在浏览/api/{entity}/count
,我会得到值&#34; 5&#34;回。
但问题是概述列表/api/{entity}/
不再有效。它说:
ExceptionMessage: "Multiple actions were found that match the request"
我已尝试使用&#34; Route&#34;属性和路由的顺序,但我无法得到它(这是:一切都像以前一样工作+在API中添加&#34; count&#34;)。我也在SO上找了解并发现How to add custom methods to ASP.NET WebAPI controller?之类的线索,但我仍然无法工作:(
有什么想法吗?
日Thnx。
答案 0 :(得分:0)
这是因为/{id}/{function}
被定义为API路线的可选参数,两条路线都与提供的网址相匹配。
没有必要定义另一个路径,只需在控制器中定义方法并用[HttpGet]
属性装饰它,你应该没问题。
答案 1 :(得分:0)
在未指定/ count时,您为计数操作配置的新路由与system.url-prefix
冲突。
您可以移除新路线并使用默认[GET] api/{entity}/
,当您拨打网址/api/{controller}/{action}
答案 2 :(得分:0)
经过大量的搜索,我已经制定了以下不需要任何新路线的解决方案 根据我的搜索,它更“RESTfull”。
我选择了/api{entity}?count
查询参数并在响应标头“X-Total-Count”中传递计数。
但问题是,我现有的GET方法已经返回了一个我不能改变的Generic IList 没有打破API。我也不能只返回一个“对象”,它是一个列表或int,取决于是否 提供了“count”查询参数,因为它打破了Swagger文档(它不再看到返回类型)
我创建了一个新类CountList:
公共接口IHasCount { int TotalCount {get; } }
public class CountList<T> : List<T>, IHasCount
{
public int TotalCount { get; set; }
public CountList(int count)
{
TotalCount = count;
}
public CountList(IList<T> list )
{
this.AddRange(list);
this.TotalCount = list.Count;
}
}
继承List的一个很好的副作用是在json序列化过程中剥离了额外的信息 所以我可以安全地返回一个Countlist而不是List,而现有的客户现在不会有差别!
然后,为了从Countlist中提取计数并将其放入响应头,我做了一个小动作过滤器:
public class GetCountFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
var counter = (actionExecutedContext.ActionContext.Response.Content as ObjectContent)?.Value as IHasCount;
if (counter != null)
actionExecutedContext.ActionContext.Response.Headers.Add("X-Total-Count", counter.TotalCount.ToString());
}
}
然后我装饰了我的Get方法:
[HttpGet]
[GetCountFilter]
public async Task<CountList<T>> GetOverview()
{
//special case, we only need the count !
if (ServerContext.QueryFilter.CountOnly) //custom object that parses the queryParameters
{
//todo, but out of scope here,, make a real Count method in the manager that actually executes a count query instead of fetching the whole list
var count = (await _entityManager.GetOverview()).Count;
var result = new CountList<T>(count);
return result;
}
//return the full list
return new CountList<T>( await _entityManager.GetOverview());
}
所以,作为一个结果,当一个客户调用/api/{entity}
时,他像往常一样得到概述,并附加了
填写了X-Total-Count标头。
当他调用/api/{entity}?count
时,他会得到一个空列表,但总计数仍在标题中!
这对我有用!如果我完全没有在房间里看到大象,请告诉我!