dell c# rest servicestack

c# - dell - Cómo implementar la llamada al servicio Eliminar mediante ServiceStack



servicestack ormlite (2)

Consulte esta respuesta anterior para obtener detalles sobre cómo diseñar una API REST-ful con ServiceStack .

CustomerRestExample contiene un ejemplo completo e independiente de un Servicio REST ServiceStack del cliente:

Definición de servicio al cliente

A continuación, se incluye un ejemplo de las rutas y solicitudes DTO personalizadas de lo que podría ser un típico servicio REST del cliente:

[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; } }

Modelo OrmLite POCO:

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

Esencialmente, las Rutas Personalizadas identifican el Recurso mientras que el VERBO HTTP indica la operación en ese Recurso. Ver las solicitudes HTTP lo aclara un poco:

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

Implementación de servicio al cliente

Con las definiciones de DTO anteriores en el lugar, ahora podemos implementar este Servicio de REST de Cliente agregando una implementación para cada DTO de Solicitud, en este ejemplo usando 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); } }

Ejemplo de uso del cliente

Con la implementación del servicio REST del cliente anterior, podemos reutilizar los DTO de solicitud con los clientes del servicio .NET de ServiceStack para proporcionar una API de tipo integral de extremo a extremo sin código genérico, es decir:

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

Los comentarios anteriores incluyen las operaciones HTTP realizadas en cada ejemplo de cliente de servicio.

Tengo un par de preguntas relacionadas con la implementación del servicio REST usando ServiceStack.

  1. Para la operación GET, defino mi DTO de solicitud como a continuación:

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

Aquí "GetCustomer" es DTO de solicitud y "GetCustomerResponse" es DTO de respuesta. Pero para la operación PUT / POST / DELETE, solo necesito saber si la operación se realizó correctamente o no, y si es ''no'', entonces, ¿cuál es la excepción? Entonces, ¿cuál debería ser mi definición de dto de solicitud para POST / PUT / DELETE? ¿Debería usar IReturnVoid como se muestra a continuación?

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

Si tengo que usar IReturnVoid, ¿cómo puedo recuperar cualquier información de excepción que pueda ocurrir al comprometer mi operación?

En el documento de manejo de errores para la pila de servicios está escrito y cito a continuación

Tipos de respuesta de error

La respuesta de error que se devuelve cuando se lanza una excepción varía según si existe o no una DTO de respuesta {RequestDto} con nombre convencional.

Si existiera:

Se devuelve la respuesta {RequestDto}, independientemente del tipo de respuesta del método de servicio. Si el DTO de respuesta {RequestDto} tiene una propiedad ResponseStatus, se completa, de lo contrario no se devolverá ResponseStatus. (Si ha decorado la clase de respuesta {ResponseDto} y las propiedades con los atributos [DataContract] / [DataMember], entonces ResponseStatus también necesita ser decorado, para que se llene).

De lo contrario, si no:

Un ErrorResponse genérico se devuelve con una propiedad ResponseStatus poblada.

Los clientes del servicio gestionan de forma transparente los diferentes tipos de respuesta de error, y para formatos sin esquema como JSON / JSV / etc. no hay una diferencia real visible entre la devolución de un ResponseStatus en una ErrorResponse personalizada o genérica, ya que ambos emiten la misma respuesta en el cable.

Lo que no obtengo de arriba es ¿cuál debería ser el tipo de devolución para mi método Delete en la implementación de mi servicio? ¿Cómo puedo implementar mi método de eliminación sin definir la eliminación de la DTO de la respuesta, pero aún así puedo recuperar la información de la excepción ''ErrorResponse''?

  1. ¿Es posible definir una ruta con el verbo "DELETE"? Tengo la siguiente implementación.

Ruta:

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

Implementación del método:

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

Pero siempre que llamo a esto eliminar usando mi cliente, siempre obtengo la excepción "NotFound". Probé con diferentes clientes, pero con todos obtengo el error 404.

Uno de los enlaces de referencia disponibles junto con el documento de la función del servidor reutiliza el verbo "OBTENER" y "ELIMINAR" juntos.

Otro enlace sugiere que no todos los navegadores admiten operaciones de eliminación.

Entonces me pregunto cómo debería implementarse la operación Eliminar.


Obtuve la solución para mi segunda pregunta de seguir dos enlaces: 1. Enlace1 2. Enlace2

No entiendo completamente esta solución pero hacer los cambios anteriores funcionó para mí y ahora puedo llamar a la función Eliminar desde cualquier cliente.

Para la primera pregunta, los pls refieren la respuesta de @mythz a continuación en detalle.