我对 Asp.NET MVC控制器在设计服务时的工作方式非常满意。但是,新的 WebAPI 控制器。我应该如何在这里设计我的服务?
假设我们有 3 种不同的列出方式,例如用户。
获取10 个最新、全部获取、非活动或其他什么。
那么您将如何在WebAPI中解决此问题
IEnumerable<User> Get10Latest()
IEnumerable<User> GetAll()
IEnumerable<User> GetInactive()
这是行不通的,因为它们具有相同的参数签名。那么在这里设计它的正确方法是什么?
通过使用操作参数,可以在一个控制器中为单个 HTTP 方法支持多个方法。
例如
public class UsersController : ApiController
{
[ActionName("All")]
public HttpResponseMessage GetAll()
{
return new HttpResponseMessage();
}
[ActionName("MostIQ")]
public HttpResponseMessage GetMostIQ()
{
return new HttpResponseMessage();
}
[ActionName("TenLatest")]
public HttpResponseMessage GetTenLatest()
{
return new HttpResponseMessage();
}
}
不幸的是,我还没有找到一种方法可以让单个控制器同时处理有动作和没有动作。
例如
public class UsersController : ApiController
{
[ActionName("")] // Removing this attribute doesn't help
public HttpResponseMessage Get()
{
return new HttpResponseMessage();
}
[ActionName("All")]
public HttpResponseMessage GetAll()
{
return new HttpResponseMessage();
}
[ActionName("MostIQ")]
public HttpResponseMessage GetMostIQ()
{
return new HttpResponseMessage();
}
[ActionName("TenLatest")]
public HttpResponseMessage GetTenLatest()
{
return new HttpResponseMessage();
}
}
能够对集合资源及其所有子集使用单个控制器会很好。
有人可能会为此把我包在指关节上,但您需要配置路由来处理 Gets。这就是我如何让它与上述操作一起工作:
config.Routes.MapHttpRoute(
name: "CustomApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { id = RouteParameter.Optional }
);
因此,现在您的请求将通过路由模板映射到正确的控制器 -> 操作。请注意,新路由需要首先在 WebApiConfig.cs 中注册。如果保留旧的,则默认的。
编辑
重新阅读这个问题后,我意识到我并没有完全回答设计问题。我认为从 REST 的角度来看,一种方法是使用单独的资源来公开正确的集合(例如 Get10Late),因为我假设通过服务公开确切的数据子集是有业务原因的。在这种情况下,您将通过其自己的控制器中的单个 Get 公开该资源(如果这是所需的行为)。
那么为什么没有这样的网址:
GET /users
GET /users/latest
GET /users/inactive
使用路由,您可以将它们路由到
public classs UserController : ApiController
{
public IEnumerable<User> Get(string mode)
{
// mode is in routing restricted to be either empty, latest, or inactive
}
}
否则,请使用多个控制器。在 Web API 中使用操作名称是一种错误的方法。