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

How to implement Delete service call using ServiceStack

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

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

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

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

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

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

在服务栈的错误处理文档中有写,我在下面引用

Error Response Types

The Error Response that gets returned when an Exception is thrown varies on whether a conventionally-named {RequestDto}Response DTO exists or not.

If it exists:

The {RequestDto}Response is returned, regardless of the service method's response type. If the {RequestDto}Response DTO has a ResponseStatus property, it is populated otherwise no ResponseStatus will be returned. (If you have decorated the {ResponseDto}Response class and properties with [DataContract]/[DataMember] attributes, then ResponseStatus also needs to be decorated, to get populated).

Otherwise, if it doesn't:

A generic ErrorResponse gets returned with a populated ResponseStatus property.

The Service Clients transparently handles the different Error Response types, and for schema-less formats like JSON/JSV/etc there's no actual visible difference between returning a ResponseStatus in a custom or generic ErrorResponse - as they both output the same response on the wire.

我没有从上面得到的是我的服务实现中 Delete 方法的 return 类型应该是什么?我如何在不定义删除响应 DTO 的情况下实现我的删除方法,但我仍然能够检索 'ErrorResponse' n 异常信息?

  1. 是否可以用"DELETE"动词定义路由?我有以下实施。

路线:

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

方法实现:

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

但是每当我使用我的客户端调用这个删除时,我总是得到 "NotFound" 异常。我尝试了不同的客户端,但都出现了 404 错误。

与 Servicestack 文档一起可用的 reference link 之一一起重用了 "GET" 和 "DELETE" 动词。

另一个 link 表明并非所有浏览器都支持删除操作。

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

有关如何设计 REST-ful API with ServiceStack 的详细信息,请参阅之前的回答。

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

客户服务定义

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

[Route("/customers", "GET")]
public class GetCustomers : IReturn<GetCustomersResponse> {}

public class GetCustomersResponse
{
    public List<Customer> Results { get; set; } 
}

[Route("/customers/{Id}", "GET")]
public class GetCustomer : IReturn<Customer>
{
    public int Id { get; set; }
}

[Route("/customers", "POST")]
public class CreateCustomer : IReturn<Customer>
{
    public string Name { get; set; }
}

[Route("/customers/{Id}", "PUT")]
public class UpdateCustomer : IReturn<Customer>
{
    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 定义,我们现在可以通过为每个请求 DTO 添加一个实现来实现这个客户 REST 服务 - 在这个例子中使用 OrmLite:

public class CustomerService : Service
{
    public object Get(GetCustomers request)
    {
        return new GetCustomersResponse { Results = Db.Select<Customer>() };
    }

    public object Get(GetCustomer request)
    {
        return Db.SingleById<Customer>(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<Customer>(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<Customer>(request.Id);
    }
}

客户使用示例

通过上述客户 REST 服务实现,我们可以将 Request DTO 与 ServiceStack 的 .NET Service Clients 重用,以提供端到端类型化 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

以上评论包括在每个服务客户端示例中执行的 HTTP 操作。

我通过以下两个链接找到了第二个问题的解决方案: 1. Link1 2. Link2

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

第一个问题,详细请参考下方@mythz的回复