我正在尝试在我们为业务创建的服务中建立编码模式(一些规则)。 我们遵循apigree为设计RESTful服务而制定的基本指导。
我们希望采用的规则之一是阻止我们不想支持的某些路由和动词组合。据推测,我们会发回一个HttpStatusCode.NotSupported用于这些非法组合,也许是一个人类可读的消息?
我们希望支持的法律组合是:
GET /resource - lists all resources
GET /resource/{id} - retrieves specific resource by ID
POST /resource - adds a new resource
PUT /resource/{id} - updates specific resource by ID
DELETE /resource/{id} - deletes specific resource by ID
我们明确不想支持一些非法组合。
POST /resource
PUT /resource
DELETE /resource
我们确实为每条支持的路线提供验证器。 但是我们的代码库中没有任何定义的非法路由。
从测试中我们了解到,如果客户端发送带有空白id(string.Empty)的GET /resource/{id}
请求,那么ServiceStack magic不会为该请求执行验证器(GET /resource/{id}
),但是而是重定向到GET /资源。我们认为DELETE /resource/{id}
和PUT /resource/{id}
也是如此。但是这些'默认'行为都不可取,我们宁愿返回一个HttpStatusCode.NotSupported或一些标头指向客户端到API文档(或一些此类指导)。
您能否建议在框架中明确处理这些案例的一些选项?
欢呼声
答案 0 :(得分:5)
如果您只想允许某些调用约定,那么您应该明确允许使用路径定义,例如:
[Route("/resource", "GET")]
public class GetAllResources {}
[Route("/resource/{Id}", "GET")]
public class GetResource
{
public int? Id { get; set; }
}
[Route("/resource", "POST")]
public class CreateResource { ... }
[Route("/resource/{Id}", "PUT")]
public class UpdateResource
{
public int Id { get; set; }
...
}
[Route("/resource/{Id}", "DELETE")]
public class DeleteResource
{
public int Id { get; set; }
...
}
在您的服务中,只匹配您指定的动词:
public class ResourceServices : Service
{
public object Get(GetResources request) { ... }
public object Get(GetResource request) { ... }
public object Post(CreateResource request) { ... }
public object Put(UpdateResource request) { ... }
public object Delete(DeleteResource request) { ... }
}
什么不匹配只是一个 404 NotFound ,因为没有匹配的路由可以处理请求。
否则,您可以创建服务以专门捕获非法请求并根据需要对其进行处理,例如:
[Route("/resource", "DELETE PUT")]
public class IllegalActions {}
public class ResourceServices : Service
{
public object Any(IllegalActions request)
{
return new HttpError(HttpStatusCode.NotAcceptable, "ActionNotSupported");
}
}
Error Handling wiki在显示ServiceStack中可用的所有错误自定义项方面做得很好。能够将C#异常映射到Http状态代码在这里也很有用:
SetConfig(new HostConfig {
MapExceptionToStatusCode = {
{ typeof(NotImplementedException), (int)HttpStatusCode.NotAcceptable },
{ typeof(NotSupportedException), (int)HttpStatusCode.NotAcceptable },
}
});