2

Background (you might want to skip this bit, it's here just in case you want context)

I saw from questions like this ServiceStack CRUD Service routing Documentation that the documentation has a weird way of explaining something that takes what I'm used to (WebApi and controller based routing) to a message oriented routed mechanism requiring us to define a request, response, and a service class with methods in order to handle each and every request.

I'm in the process of converting an existing code base from WebAPI + OData based services to service stack to determine the difference / modelling changes that the two designs require.

The problem domain

There are many requests I currently make that don't really require any parameters (simple get requests) and yet i'm forced to both create, instantiate and then pass to a service method a DTO in this situation as without such a DTO I can't define the route.

Why? this is confusing!

What is the relationship between the DTO, the methods in a service and the routing / handling of a request because i currently have lots of "service" classes in my existing stack that are basically ...

public class FooService : CRUDService<Foo> { /* specifics for Foos */ }

public abstract class CRUDService<T> : ICRUDService<T>
{
    public T GetById(object Id) { ... }
    public IEnumerable<T> GetAll() { ... }
    public T Add(T newT) { ... }
    public T Update(T newVersion) { ... }
    public bool Delete(object Id) { ... }
}

... how do i get from that for 100 or so services to making this a functional service stack implementation because at the moment my understanding is that I can't pass scalar values to any of these methods, I must always pass a DTO, the request DTO will define the route it handles and I must have a different request and response DTO for every possible operation that my API can perform.

This leaves me thinking I should resort to T4 templating to generate the various DTO's saving me time hand cranking hundreds of basically empty DTO's for now.

My question(s)

It boils down to How do I convert my codebase?

that said, the "sub parts" of this question are really sub questions like:

  • What's best practice here?
  • Am I missing something or is there a lot of work for me basically building empty boiler plate DTO's?
  • How does Service stack wire all this stuff up?

I was told that it's "better than the black box of OData / EF" but this at face value appears to hide a ton of implementation details. Unless i'm just confused at something in the design ethos.

War
  • 8,539
  • 4
  • 46
  • 98

1 Answers1

1

Each Service in ServiceStack requires a concrete Request DTO which is used to define your Services contract.

As ServiceStack is a message-based services framework, the Typed Request DTO is fundamental in how ServiceStack works which "captures the Request" that Services are invoked with, which is also passed down through all ServiceStack filters, e.g:

overall architecture

The Request DTO is also all that's needed to be able to invoke a Service from any client, including MQ Clients:

.net service clients

And by following the Physical Project Structure that ServiceStack Project templates are configured with where all DTOs are kept in a dependency/impl-free ServiceModel project that ServiceStack's .NET generic Service Clients can reference directly to enable an end-to-end Typed API without code-gen, e.g:

var response = client.Get(new MyRequest { ... });

The Request DTO being a "message" uses a POCO DTO to define its contract which is better suited for versioning as they can be extended without breaking existing classes and since the Request DTO is the definition and entry-point for your Service it's also what most of ServiceStack's other features is built-around, needless to say its important.

Sharp Script for code-generation

If you have so many CRUD Services that you wish to auto-generate DTOs for them I'd recommend taking a look at #Script which is a dynamic .NET Scripting language that defaults to a Template language mode that uses familiar JS syntax for expressions and the ideal handlebars syntax for blocks for templating.

The stand-alone Script Support includes Live Preview support whose instant feedback makes it highly productive and also includes built-in support for querying databases.

Although OrmLite is a code-first ORM, it does include T4 support for initially generating data models.

AutoCRUD Preview

Since you're looking to generate a number of CRUD Services you may want to checkout the preview release of AutoCRUD that's now available on MyGet.

It’s conceptually the same as “Auto Query” where you just need to implement the Request DTOs definition for your DB Table APIs and AutoQuery automatically provides the implementation for the Service.

mythz
  • 141,670
  • 29
  • 246
  • 390
  • I have an existing DB, and i've replaced my root DataContext implementation with an OrmLite based implementation that I have inherited in my various DBs "models". That then plugs in to my service layer fine, which I made my Service base class inherit from the Service stack one thinking "that should do it", then i discovered that the services are implementations and are given these DTO's that actually have the routing info on them. That's where I couldn't quite see how it all plugs together. In short, the relationship between a request DTO a service and a response DTO is sort of a magic box. – War Mar 14 '20 at 18:09
  • to quote you: "A fundamental concept in ServiceStack is that every service needs to be called with a Request DTO." ... awesome, how does this relationship work, can I specify or tweak it, can a request DTO be routed to multiple service methods? Essentially I want to give GetRequest to a Service method ... is this possible or am i forced to concretely specify each sub type of GetRequest despite there being literally no difference in all my Get Requests "structure". – War Mar 14 '20 at 18:13
  • @War The Request DTO is the definition, the class that inherits `Service` with a [public method with a single Request DTO Parameter named after a HTTP Method](https://docs.servicestack.net/api-design#basic-example---handling-any-http-verb) is its Service implementation, the response is whatever the Service implementation returns which is recommended (tho optional) to be annotated on the Request DTO with the `IReturn` interface marker as it provides generic Service Clients a nicer typed API. – mythz Mar 14 '20 at 18:39
  • Yeh, i understand ... thanks for stick with me whilst I get my head round this new way of looking at API interface design. I created another question though with just my routing issue explained a bit differently in the hope this might clarify my issue .. https://stackoverflow.com/questions/60686237/servicestack-is-context-based-routing-specified-in-the-url-possible – War Mar 14 '20 at 19:02