2

I am unable to find documentation (Clear or otherwise) that explains how to implement a Service in Service Stack with multiple methods. All examples show a service class with one method only. I cant imagine if you have a service with 4+ methods, that your really need to make 4+ service classes, 4+ Request DTO's and 4+ response DTO's. ( As shown here )

Example:

A Service with 4 Search methods ( method(Identifer1), method2(identifer2), method3(identifer3))

Based on the documented structure of a Request DTO ( Service Stack Wiki , and Creating your First Web Service ) , The Request DTO's Class Attributes, Control the Routing to the Service Class, (If I understood that correctly, but again I am looking for Documentation or an example)

The documentation on routing is a little fuzzy, as most examples do not follow the defined naming convention for Request/Response DTo's as outlines in the "Your First Web Service Explained"

I have also read this SO Post, but the I am left with the same questions after following the advice.

Community
  • 1
  • 1
Rex Whitten
  • 725
  • 1
  • 7
  • 20
  • thanks but sometimes 2 + 2 != 5. Plus one for the advice. – Rex Whitten Dec 30 '12 at 00:14
  • Thanks for this, I came to the same conclusion after reading the docs. Compared to something like WebApi it seems that service stack requires you to tell a DTO what route handles it ... more weirdness, then the basically "boiler plate CRUD based DTO bloat" that will come out of this seems nuts. – War Mar 13 '20 at 23:25

1 Answers1

5

I cant imagine if you have a service with 4+ methods, that your really need to make 4+ service classes, 4+ Request DTO's and 4+ response DTO's.

No you need 1 service class with 4 methods - each method of course taking a request Dto and returning a Response Dto. Obviously for some methods you might not need a response Dto

For example, here's how a typical service with 5 methods might look like:

public class ProductsService: Service
{
    [Route("/products")]
    public class GetProductsRequest: IReturn<List<ProductResponse>> {}

    public class ProductResponse
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public object Get(GetProductsRequest request)
    {
        IEnumerable<ProductResponse> response = ...
        return response;
    }

    [Route("/products/{id}")]
    public class GetProductRequest: IReturn<ProductResponse> 
    {
        public int Id { get; set; }
    }

    public object Get(GetProductRequest request)
    {
        ProductResponse response = ...
        return response;
    }

    [Route("/products")]
    public class CreateProductRequest 
    {
        public string Name { get; set; }
    }

    public object Put(CreateProductRequest request)
    {
        ... create the product here
        return new HttpResult { StatusCode = HttpStatusCode.Created };
    }

    [Route("/products/{id}")]
    public class UpdateProductRequest
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public object Patch(UpdateProductRequest request)
    {
        ... update the product here
        return new HttpResult { StatusCode = HttpStatusCode.Accepted };
    }

    [Route("/products/{id}")]
    public class DeleteProductRequest
    {
        public int Id { get; set; }
    }

    public object Delete(DeleteProductRequest request)
    {
        ... delete the product here
        return new HttpResult { StatusCode = HttpStatusCode.Accepted };
    }
}

I've put the Request and Response DTOs as nested classes to the service, but it would make it more readable to have them in separate files:

public class ProductsService: Service
{
    public object Get(GetProductsRequest request)
    {
        IEnumerable<ProductResponse> response = ...
        return response;
    }

    public object Get(GetProductRequest request)
    {
        ProductResponse response = ...
        return response;
    }

    public object Put(CreateProductRequest request)
    {
        ... create the product here
        return new HttpResult { StatusCode = HttpStatusCode.Created };
    }

    public object Patch(UpdateProductRequest request)
    {
        ... update the product here
        return new HttpResult { StatusCode = HttpStatusCode.Accepted };
    }

    public object Delete(DeleteProductRequest request)
    {
        ... delete the product here
        return new HttpResult { StatusCode = HttpStatusCode.Accepted };
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks alot. I think I just learned ALOT about this from this example. Tell me you did not pull this from documentation? – Rex Whitten Dec 29 '12 at 23:25
  • 2
    Everything you need to know is in the documentation. The rest comes by rolling your sleeves and start playing with it. – Darin Dimitrov Dec 29 '12 at 23:27
  • I was not able to find this implementation in the documentation.(original problem) Again, after seeing this, I can see why the examples in the documentation were written that way. I wish the above was in the documentation, with the explanation you gave. – Rex Whitten Dec 30 '12 at 00:15