我通过以下步骤找到了这个问题:
使用已安装的项目模板
转到Controllers / ValuesController.cs,有两个 Get 方法,如下所示:
public IEnumerable<string> Get()
//这个提供 GetAll 功能
public string Get(int id)
//这个是 GetOneById
我不喜欢这种设计,因为我认为这两种api方法可以组合成一种:
public IEnumerable<string> Get(string ids)
当ids为空时,它返回所有记录,否则返回结果ids(看起来像id1,id2,id3 ......)
我也修改了路线:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{ids}",
defaults: new { ids = RouteParameter.Optional }
);
现在我觉得一切都准备好了。但是,当我在浏览器中访问/values
时(未指定ids参数),我被告知“未找到任何操作”,直到我为ids
添加默认值:
public IEnumerable<string> Get(string ids = null)
从现在开始,一切都按照我的预期运作。我仍然无法移动路线中的defaults
参数。这意味着:代码将ids参数声明为可选两次。
查看位于System.Web.Http.Controllers.ActionSelectorCacheItem.FindActionUsingRouteAndQueryParameters
方法的MVC4的源代码,我可以看到在找到正确的操作时忽略路由中定义的可选参数。就个人而言,我认为这真的很糟糕,即使是变通方法也很容易。或者我误解了路线和行动方法之间的关系?我认为路由是用于帮助请求查找其相应操作的规则,而“参数是可选的”正是规则的一部分。
答案 0 :(得分:4)
你可能会有一个争论,这对于相对直接的事情来说是一个尴尬的解决方案,但我认为根本原因是因为你试图将'GetAll'和'GetOneById'都推到同一个方法中。
如果您愿意拆分控制器中的方法,则可以使路径配置脱离问题。恕我直言,这不是一件坏事;它符合关注点分离原则。它也不代表任何代码重复,因为您可以集中逻辑来访问要返回的对象。
这些控制器方法应该为您提供所需的路线,而无需调整路线配置:
[HttpGet]
public IEnumerable<string> GetAll()
{
return GetStrings(new int[]{});
}
[HttpGet]
public string GetOneById(int id)
{
return GetStrings(new int[]{id}).FirstOrDefault();
}
private IEnumerable<string> GetStrings(int[] ids)
{
return // fetch strings using int array
}
答案 1 :(得分:1)
您可以选择将值作为查询字符串
public class PaymentsController : ApiController {
[HttpGet]
public Person GetValues(string ids = null)
{
return new Person() { FirstName = "Michael" };
}
}
public class Person
{
public string FirstName { get; set; }
}
}
我能够使用以下两种途径访问此路线:
注意:除了默认
之外没有任何特殊路由