Firstly I want to point out the patterns and core ideas ServiceStack is
based around and tries to promote - they are all short but highly
recommended reading.
Here are the very few patterns I follow and find fundamentally important
when developing web services, which are strangley enough also available on
the MSDN <http://msdn.microsoft.com/en-us/library/ff649585.aspx>
website<http://msdn.microsoft.com/en-us/library/ff650101.aspx>but for
whatever other reason is discouraged by WCF:
- Remote Facade
Pattern<http://martinfowler.com/eaaCatalog/remoteFacade.html>-
Promoting the design of coarse grain and batchful interfaces whenever
you
communicate across process boundaries.
- DTO pattern
<http://martinfowler.com/eaaCatalog/dataTransferObject.html>- Special
purpose POCOs that define your web services payloads.
- Service Gateway
pattern<http://martinfowler.com/eaaCatalog/gateway.html>- To
encapsulate your client and server communications.
I also believe these patterns promote 'web service development best
practices' that better lend themselves in designing SOA systems as it leads
to fewer, less client-specific and more re-usable services. I've created a
small gist to show the contrast between the RPC methods that I believe WCF
encourages and the equivalent services I hope to encourage with
ServiceStack:
https://gist.github.com/1386381
The above gist also shows you how you can easily add extra service
functionality to the Request DTO and data to the Response DTO in a way that
doesn't effect old/existing clients as the extra functionality/data just
gets ignored by unaware clients. The JSON and JSV endpoints and serializers
are extremely resilient and can withstand some extreme versionability of
your services without
error<https://github.com/ServiceStack/ServiceStack.Redis/wiki/MigrationsUsi...>
.
The above patterns (and many more) are discussed in detail in Martin
Fowlers excellent Patterns of Enterprise Application
Architecture<http://www.martinfowler.com/books.html#eaa>
.
> So what you're saying is that keeping each request as a single DTO
> simplifies the use of certain patterns on the clients, such as using a
> queue. Okay, I will somewhat buy that, but the client still needs to know
> the URL to send the DTO to..
ServiceStack automatically exposes Sync and Async Urls for each of your web
services (see: "*The different ways of calling your Web Service*" in
http://www.servicestack.net/ServiceStack.Hello/)
This lets you provide a base url into any ServiceClient which lets you call
each web service. Here's a Unit/Integration Test example that allows the
same unit test to be executed by all ServiceClients using the same Base
Url. No custom routes were needed:
https://github.com/ServiceStack/ServiceStack/blob/master/tests/Servic...
This is effectively impossible to achieve if you had used code-gen clients,
which lets you bind to an implementation-free IServiceClient that allows
you to switch formats (ServiceClients) at anytime without any rewrites
required.
The custom routes are there if you want to provide REST-ful canonical urls
for all your services if you prefer - though it's entirely optional and not
needed by default.
I don't have any problem with the DTO boilerplate directly. What I find
> awkward is the connection between the DTOs, services, and routing. I
> consider the URL and HTTP verb to be effectively one and the same, so what
> bugs me is the fact that the URL is defined by routing, and the verb is
> defined by the service code implementation (and also, possibly, the
> routing). On top of that, the service is not connected directly to the
> routing -- it's connected implicitly via the DTO.
Yes this is the ServiceStack idiom where the *Request DTO* is your service
- it defines the contract and is all you need to identify and invoke it. So
in ServiceStack the Request DTO == Your service, which is why I suggest you
make it a first-class concept and you drop any 'Request' suffix you might
have as the Request DTO is your code-first contract and everything else
hangs off it.
I personally don't like this at all. This now looks like RPC: you have a
> verb in the URL.
You may not like it but it's extremely intuitive as to which method gets
invoked via each HTTP Verb. The only difference between inheriting from
ServiceBase and RestServiceBase is that ServiceBase.Run() gets invoked for
every HTTP verb on any endpoint with any format, etc whilst
RestServiceBase.OnGet()/OnPost() etc will execute different methods based
on the HTTP Verb which is ultimately what you want when you're implementing
a REST-ful api.
I also really don't like having (request.Method == "load") in the service
> code. It feels to me like the framework only did 80% of the work it should
> have
Up to this point is where ServiceStack marshals the request into a C#
Request DTO (via any endpoint, format or calling convention) is the bottom
most point where it works naturally as expected, any further then it starts
to become opinionated, you lose debuggability and "magic behaviour" starts
to occur. Like I've articulated I dislike marshalling to a RPC method
signature as I think it promotes the wrong service API design and
implementation also once you lose the Request DTO you start to lose your
ability to cleanly defer, proxy or cache the request.
It does somewhat, but I don't really get the full motivation yet. Since no
> matter what, you're still tied to the URL, any attempt to abstract that
> away actually seems counter-intuitive.
You're not tied to the url if you use the auto generated routes (i.e. you
only need supply the base url). If you're just doing a client/server app
where you provide an .NET client gateway that wraps your services i.e. the
client never sees the custom url routes then I don't believe you should
have any as it just adds an extra layer of un necessary 'industrial
knowledge' i.e. more friction / work that needs to be done and that can get
out of sync with your services.
In the end, I'm just looking to simplify mapping between URLs and service
> code.
You should be able to provide the custom Url routing using the attributes
and conventions you prefer with your own base class. And like I said
earlier if there is strong demand for this I can include as an opt-in, in
the framework.
By letting you do it (and not the framework) you get debuggability on the
area which I believe will prove problematic and other users that don't like
this indirection (i.e. me) needn't suffer the additional perf overhead for
a feature they don't use.
What I was hoping to get out of this thread is an understanding of why
> having a DTO is beneficial, but so far I don't get it. You briefly
> mentioned using queues, and I think were hinting at abstracting away the
> implementation (which I guess means the URLs the client points at?) but I
> fail to understand how it's possible to have the client ignore the URL, and
> why knowing the URL (and even having parameters in it) cause any problems
> on either the client or server. Is there an example somewhere you can point
> me at, where it's clear that the single request DTO is beneficial, and it's
> not possible to do it using my proposed code?
All the HTTP Service Clients in ServiceStack:
https://github.com/ServiceStack/ServiceStack/tree/master/src/ServiceS... including the non-HTTP Messaging, Redis MQ and RCON clients can invoke a
service with just the Request DTO, it can do so providing a typed API
without any code-gen simply because everything hangs off the Request DTO
which maps 1:1 with your service. For better or worse the Request DTO *is
your service interface* you will have a lot less time fighting the
framework if you follow this single fundamental convention.
I fail to understand how it's possible to have the client ignore the URL
All HTTP Service Clients use the auto provided urls as documented in
ServiceStack.Hello <http://www.servicestack.net/ServiceStack.Hello/> to
invoke any of your services with just your services BaseUri as seen in
Integration
and Unit test examples<https://github.com/ServiceStack/ServiceStack/blob/master/tests/Servic...>
.
You can defer the execution of your service for an instant response time
and added reliability/durability by dropping it in a MQ like:
using (var producer = MessageFactory.CreateMessageProducer()) {
producer.Publish(request);
}
So far the Messaging Service API in ServiceStack has an InMemory,
Redis-backed MQ and TCP/RCON implementations with a very extensible
interfaces so you can provide your own MQ adapters.
In order to archive, log or reconstruct the request for later playback you
only need to serialize (and playback) the Request DTO - this is impossible
to do elegantly if you mapped to an RPC method signature.
Likewise to delegate/proxy the request to a Sub System (e.g. Master>Shards)
you could easily do it with something like:
public override object Run(Users request) {
var shardClient = this.ShardClients[request.UserId % ShardsCount];
return shardClient.Send<UsersResponse>(request);
}
Basically ServiceStacks 'message-based' approach allows you to solve many
high-level messaging integration patterns more elegantly than an RPC
approach.
It increases productivity since there is no code-gen, increases the
re-usability and versionability of your services and the added boiler plate
should really be inconsequential since you should have less but more
coarse-grained/batchful services.
Hope this helps explain the philosophy behind ServiceStack further :)
Cheers,
On Sun, Dec 11, 2011 at 9:10 PM, gregmac <g
...@gregmaclellan.com> wrote:
> Hi Demis,
> On Friday, 9 December 2011 12:56:40 UTC-5, mythz wrote:
>> I try to promote a single message-based DTO approach to designing and
>> invoking services.
>> There is major usability and re-usability advantages by
...
read more »