如何使用ServiceStack实现删除服务调用

我有几个与使用ServiceStack的REST服务实现相关的问题。

  1. 对于GET操作,我将请求DTO定义如下:

    [Route("/Customer/{ID}", Verbs = "GET")] public class GetCustomer : IReturn { .... .... } 

这里“GetCustomer”是请求DTO,“GetCustomerResponse”是响应DTO。 但是对于PUT / POST / DELETE操作,我只需要知道操作是否成功提交,如果’不’那么什么是exception。 那么对于POST / PUT / DELETE我的请求dto定义应该是什么? 它应该使用如下所示的IReturnVoid吗?

 [Route("/Customer/{ID}", Verbs = "DELETE")] public class DeleteCustomer : IReturnVoid { .... .... } 

如果我必须使用IReturnVoid,那么我如何检索在提交我的操作时可能发生的任何exception信息?

在服务堆栈的error handling文档中,它是写的,我在下面引用

错误响应类型

抛出exception时返回的错误响应取决于是否存在常规命名的{RequestDto}响应DTO。

如果存在:

无论服务方法的响应类型如何,都会返回{RequestDto}响应。 如果{RequestDto}响应DTO具有ResponseStatus属性,则会填充它,否则将不返回ResponseStatus。 (如果您使用[DataContract] / [DataMember]属性修饰了{ResponseDto} Response类和属性,则还需要对ResponseStatus进行修饰以进行填充。

否则,如果不是:

返回一个通用的ErrorResponse,其中包含一个填充的ResponseStatus属性。

服务客户端透明地处理不同的错误响应类型,对于无模式格式(如JSON / JSV / etc),在自定义或通用ErrorResponse中返回ResponseStatus之间没有实际的明显区别 – 因为它们都在线路上输出相同的响应。

我从上面得到的是我的服务实现中的Delete方法的返回类型应该是什么? 如何在不定义删除响应DTO的情况下实现我的删除方法但是我能够检索“ErrorResponse”nexception信息?

  1. 是否可以使用“DELETE”动词定义路线? 我有以下实施。

路线:

 [Route("/DeleteCustomer/{ID}", Verbs = "DELETE")] public class DeleteCustomer : IReturn { public int ID { get; set; } } 

方法实施:

 public DeleteContactResponse Delete(DeleteContact request) { ..... } 

但每当我使用我的客户端调用此删除时,我总是得到“NotFound”exception。 我试过不同的客户但是我得到了404错误。

与Servicestack文档一起提供的参考链接之一可以重复使用“GET”和“DELETE”动词。

另一个链接表明并非所有浏览器都支持删除操

所以我想知道应该如何实现删除操作?

有关如何使用ServiceStack设计REST-ful API的详细信息,请参阅此前面的答案。

CustomerRestExample包含Customer REST ServiceStack服务的完整独立示例:

客户服务定义

以下是典型客户REST服务的自定义路由和请求DTO的示例:

 [Route("/customers", "GET")] public class GetCustomers : IReturn {} public class GetCustomersResponse { public List Results { get; set; } } [Route("/customers/{Id}", "GET")] public class GetCustomer : IReturn { public int Id { get; set; } } [Route("/customers", "POST")] public class CreateCustomer : IReturn { public string Name { get; set; } } [Route("/customers/{Id}", "PUT")] public class UpdateCustomer : IReturn { public int Id { get; set; } public string Name { get; set; } } [Route("/customers/{Id}", "DELETE")] public class DeleteCustomer : IReturnVoid { public int Id { get; set; } } 

OrmLite POCO型号:

 public class Customer { [AutoIncrement] public int Id { get; set; } public string Name { get; set; } } 

本质上,自定义路由标识资源,而HTTP VERB指示对该资源的操作。 查看HTTP请求使这一点更清晰:

 GET /customers -> return all Customers POST /customers -> Create a new Customer GET /customers/1 -> return Customer 1 PUT /customers/1 -> Update Customer 1 DELETE /customers/1 -> Delete Customer 1 

客户服务实施

通过上述DTO的定义,我们现在可以通过为每个Request DTO添加实现来实现此Customer REST服务 – 在此示例中使用OrmLite :

 public class CustomerService : Service { public object Get(GetCustomers request) { return new GetCustomersResponse { Results = Db.Select() }; } public object Get(GetCustomer request) { return Db.SingleById(request.Id); } public object Post(CreateCustomer request) { var customer = new Customer { Name = request.Name }; Db.Save(customer); return customer; } public object Put(UpdateCustomer request) { var customer = Db.SingleById(request.Id); if (customer == null) throw HttpError.NotFound("Customer '{0}' does not exist".Fmt(request.Id)); customer.Name = request.Name; Db.Update(customer); return customer; } public void Delete(DeleteCustomer request) { Db.DeleteById(request.Id); } } 

客户使用示例

通过上述Customer REST Service实现,我们可以重新使用Request DTO和ServiceStack的.NET服务客户端来提供没有代码的端到端Typed API,即:

 var client = new JsonServiceClient(BaseUri); //GET /customers var all = client.Get(new GetCustomers()); // Count = 0 //POST /customers var customer = client.Post(new CreateCustomer { Name = "Foo" }); //GET /customer/1 customer = client.Get(new GetCustomer { Id = customer.Id }); // Name = Foo //GET /customers all = client.Get(new GetCustomers()); // Count = 1 //PUT /customers/1 customer = client.Put( new UpdateCustomer { Id = customer.Id, Name = "Bar" }); // Name = Bar //DELETE /customers/1 client.Delete(new DeleteCustomer { Id = customer.Id }); //GET /customers all = client.Get(new GetCustomers()); // Count = 0 

上面的注释包括在每个Service Client示例中执行的HTTP操作。

我从以下两个链接获得了第二个问题的修复: 1。Link1 2. Link2

我不完全理解这个修复,但做上述修改对我有用,现在我可以从任何客户端调用Delete函数。

对于第1个问题,请参阅下面@mythz的回复详细说明。