如何使用ServiceStack

时间:2015-05-15 14:46:26

标签: c# rest servicestack

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

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

    [Route("/Customer/{ID}", Verbs = "GET")]
    public class GetCustomer : IReturn<GetCustomerResponse>
    {
        ....
        ....
    }
    
  2. 此处“GetCustomer”是请求DTO,“GetCustomerResponse”是响应DTO。但是对于PUT / POST / DELETE操作,我只需要知道操作是否成功提交,如果'不'那么什么是异常。那么对于POST / PUT / DELETE我的请求dto定义应该是什么?它应该使用如下所示的IReturnVoid吗?

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

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

    在服务堆栈的错误处理文档中,它是编写的,我在下面引用

      

    错误响应类型

         

    抛出异常时返回的错误响应   不同于传统命名的{RequestDto}响应DTO   存在与否。

         

    如果存在:

         

    无论服务如何,都会返回{RequestDto}响应   方法的响应类型。如果{RequestDto}响应DTO有   ResponseStatus属性,它被填充,否则没有ResponseStatus   将被退回。 (如果您已装饰{ResponseDto}响应   具有[DataContract] / [DataMember]属性的类和属性   ResponseStatus也需要进行修饰,以便填充。

         

    否则,如果不是:

         

    通过填充的ResponseStatus返回一般的ErrorResponse   属性。

         

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

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

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

      [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表明并非所有浏览器都支持删除操作。

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

2 个答案:

答案 0 :(得分:13)

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

CustomerRestExample包含Customer 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添加实现来实现此Customer 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);
    }
}

客户使用示例

通过上述Customer REST Service实施,我们可以重新使用Service Dack与ServiceStack的.NET Service Clients来提供没有代码生成的端到端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 :(得分:0)

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

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

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