Register general service that handles all dtos

Hi,

I need to create general service which have to execute all registered paths.
I am registering paths like this:

appHost.ServiceController.RegisterRestPaths(requestDtoType);
appHost.Metadata.Add(typeof(BrokerService), requestDtoType, responseDtoType);

BrokerService:

public class BrokerService : IService
{
    public object Any(object requestDto)
    {
        return "random response";
    }
}

Tomasz

Each ServiceStack Service needs a Typed Request DTO.

If you want an endpoint that handles all requests you can have your Request DTO implement IRequiresRequestStream which you can download the body and deserialize the contents yourself, e.g:

//Request DTO
public class RawBytes : IRequiresRequestStream
{
    Stream RequestStream { get; set; } // The raw Http Request Input Stream
}

//Service
public object Any(RawBytes request)
{
    byte[] bytes = request.RequestStream.ReadFully();
    string text = bytes.FromUtf8Bytes(); //if text was sent
    return text;
}

I need to create fully transparent broker of our services.
I have two limitations:

  1. firewall rule which allows only ServerB->ServerA connections
  2. I have to use existing DTO’s without rewriting anything in original app hosted on Server B. Broker must be fully transparent in order to call for example RESTful API (Servicestack messaging handles only POST requests).

My plan: Server A receives request and fully deserializes DTO. Then this DTO, alongside various IRequest data is saved to Rabbit and Server A is waiting for response.
Server B takes job from Rabbit and executes request pipeline with faked request, because I need every filter executed, as it was normal HTTP request.

I figured out how to fake request inside ServerB.
In ServerA: I don’t want to register every dto by hand, I tried to handle it with reflection. I registered every path but I have to somehow handle all dtos in one place. I thought maybe ServiceController.Execute(object requestDto, IRequest req) would be good place, but after studying logic inside ServiceController I am not so sure.

I also tried not using ServiceStack in Broker, but this complicates things much more. I would had to write deserialization logic for GET parameters for example.

It looks like you’re trying to do a lot of what ServiceStack does, but in a single Service implementation - it’s not going to work as well as you’re hoping it too. You can’t deserialize unknown byte[] into an unknown Type. You need to pass the Request DTO name at a minimum then use it to look up the Request DTO in HostContext.Metadata.GetOperationType(name), which you could use to try deserialize the body into, but it’s not going to be populated with the QueryString/FormData/etc like normal Request DTOs are and you’re not going to be able to run it through the HTTP Request Filters.

There’s a feature in ServiceStack that if you have an MQ Server registered, sending a Request to the OneWay endpoint will publish the message to the broker which may be close to what you’re looking for.

Trying to re-implement a generic service that generically deserialize any Type is going to require a lot of effort to have it work properly. You’re better off not trying to deserialize the Request DTO, capture the HTTP Request, e.g Method / Body / Path / QueryString /etc and publish that to the MQ Broker, then have the Service processing the messages of the broker use that info to recreate a HTTP Request to invoke the Service with. i.e. the Service that accepts the message and the MQ broker don’t have any knowledge of Server DTOs/Types, they’re just forwarding the HTTP Request so it can be re-created later.

I have ServiceModel dlls shared between Broker and main server app.
Request deserialization (incl. dto) works fine without service.

I will discuss your suggestions about passing raw http request through rabbit with team tomorrow. Thank you for your tips.