2
votes

Is there any way to harness or reuse the internal servicestack url route-to-service resolution to obtain the matching request DTO of that URL?

For example we have a service aggregating a list of URL strings that point to different SS services - all of which generate and return a PDF:

    public class PDFAggregationService : ServiceStack.Service
{
    public BigAssPDFResponse Any(BigAssPDFRequest request)
    {
        var response = new BigAssPDFResponse();


        //does something to fetches list of pdf generating urls
        var pdfRoutes = [
               "https://server1/route1/param/2/thing/1",
               "https://server1/route1/param/3/thing/4",
               "https://server1/route2/param/1",
               "https://server1/route3/param/1"];




        var pdfBytes = new List<object>();
        pdfRoutes.ForEach(url=>
        {

            var requestDto = ???? ;  // how to resolve a DTO from a random URL? 

            var response = Gateway.Send<object>(requestDto);

            pdfBytes.Add(response);

        })


        // does something to aggregate all pdfs into one
        // pdfBytes.ForEach(...) 

        return response;


    }
}

We want to avoid instantiating a JSONClient to just call the URLs, as all the called services are living inside the same AppHost as PDFAggreationService. (We'd also like to use a Gateway call so that we can leverage some complex logic that we have implemented in various request/response filters).

1

1 Answers

2
votes

I've added a new Metadata.CreateRequestFromUrl() API that wraps the boilerplate that lets you do this in this commit (now available from v5.0.3 on MyGet) which you can use to do:

var requestDto = HostContext.Metadata.CreateRequestFromUrl(url);
var responseType = HostContext.Metadata.GetResponseTypeByRequest(requestDto.GetType());
var response = Gateway.Send(responseType, requestDto);

Note your Request DTOs need to have the IReturn<T> marker interface to be able to use the Service Gateway.

This new API effectively wraps the boilerplate below to fetch the matching RestPath route definition which you can then populate with a /path/info and additional Dictionary of params that you can then send through the gateway, e.g:

var pathInfo = "/route1/param/1";
var queryParams = new Dictionary<string,string> { ... };

var route = RestHandler.FindMatchingRestPath("GET", pathInfo, out _);
var reqType = route.RequestType;
var requestDto = route.CreateRequest(pathInfo, queryParams, reqType.CreateInstance());

var resType = HostContext.Metadata.GetResponseTypeByRequest(route.RequestType);
var response = Gateway.Send(resType, requestDto);