2

What I would like to do is the following:

var client = new JsonServiceClient(ServiceUrl);
var request = new FooQuery {Id = 1};
IEnumerable<Project> response = client.Get(request);

However, my FooQuery doesn't implement any IReturn, and I'd like it not to (it's in a library without ServiceStack references). Here's my service side:

Library of business objects:

public class ProjectQuery
{
    public int Id { get; set; }
}

AppHost:

Routes.Add<ProjectQuery>("/project", "GET");

Service:

public object Get(Foo request)
{
     // do stuff.
}

Is there some nice, clean way to create the JsonServiceClient without using the IReturn interface on my business object?

mariocatch
  • 8,305
  • 8
  • 50
  • 71
  • This post here (http://stackoverflow.com/questions/12700702/servicestack-ireturn) seems to be similar to what I want... but the suggested approach doesn't work for me (doesn't even compile). – mariocatch Sep 11 '13 at 17:27
  • I think the key is to find a way to translate your `Foo` object to a URL string, correct? Then you can write simple wrapper around the `Get(string)` method. There is a `ToUrl` extension method used in some of the existing `Get` methods in the `ServiceClientBase` class but they require the request object to implement `IReturn` (and I don't see a good reason why the IReturn requirement is there, if it weren't there then I think you'd be in good shape). – Mike Mertsock Sep 11 '13 at 17:41
  • Mythz said in a previous post that if we don't use the IReturn marker on the DTO, then we can use "List response = client.Get>(new ReqDto());". I don't think he's correct, because the 2 overloads for Get() ask for either a URL, or an IReturn. My DTOs can be very complex, so I have to write a URL conversion for each of my DTOs and keep them up to date? That isn't very nice. – mariocatch Sep 11 '13 at 17:48

3 Answers3

1

Looks like there's no way not to use IReturn if you don't want to provide a URL to the JsonServiceClient Get() requests. Just decided to create another set of DTOs in my ServiceStack implementation, that are essentially mirrors of the real DTOs in another library. Then when a request comes in to my SS DTO, I create the other library's DTO, set each property, and pass it along.

Not pretty, but that's the best I could find so far.

mariocatch
  • 8,305
  • 8
  • 50
  • 71
  • 1
    FYI, Using [DTO's is recommended](http://stackoverflow.com/a/15369736/85785), you can also use the built-in [Auto Mapping](https://github.com/ServiceStack/ServiceStack/wiki/Auto-mapping) to reduce the boilerplate/effort. – mythz Sep 11 '13 at 20:44
  • This is really nice - thanks for pointing it out. I'm refactoring now to use it, but stefan2410's answer below is more in line with what I was looking for, for separation of business objects and SS. – mariocatch Sep 12 '13 at 15:01
1

I had the same problem using IReturn and Routes, as I wanted to use the DTOs
in assemblies with business logic, without ServiceStack references.

It worked for me, using in the Client Model

   public class TestRequest
   {
        public int vendorId {get; set; }
        public string barcode {get; set; }     
        public string username { get; set; }   
        public string password { get; set; } 
   }    

then in the AppHost

      Routes.Add<TestRequest( "/TestAPI/Reservation/{vendorId}/{barcode}"," GET,OPTIONS")   
            .Add<TestRequest>("/TestAPI/Reservation", "POST, OPTIONS")     

and the call for JsonServiceClient with POST

        request.vendorId=12344; 
        request.barcode="AAS1223"; 
        TestResponse response = client.Post<TestResponse>(server_ip + "/TestAPI/Reservation", request);  

OR with GET

   TestResponse response = client.Get<TestResponse>(server_ip + "/TestAPI/Reservation/12344/AAS1223?username=John&password=99");     

Then in the service Get or Post functions

      public TestResponse Get(TestRequest request)
      {    
         // request members  hold  the values of the url.
         return  DoBusinessLayerWork(request);
      }
stefan2410
  • 1,931
  • 2
  • 16
  • 21
  • So Post has a method signature that accepts the request object, but Get does not. But I did find that Send() does allow a request object to be sent... Need to do more research of the difference between Send and Get/Post/etc... – mariocatch Sep 12 '13 at 14:52
  • Looks like Get and Post simply call Send, with a hardcoded HttpMethod. Ok, so if you modify your answer to use Send instead of Post, this can be acceptable for anyone in any scenario. – mariocatch Sep 12 '13 at 14:55
  • You didn't include the Send() usage like I asked though. Using Send() in the client is the only valid answer to my question (use the service without specifying the URL, and without using Post()). If you use Send(), you only need the Http Method ("GET"), the relative URI, and the request object. – mariocatch Sep 16 '13 at 17:07
  • I use the REST API. A detailed information is here [ServiceStack C# client](https://github.com/ServiceStack/ServiceStack/wiki/C%23-client) Somebody else maybe can explain better the use of Send() in JsonServiceClient. But the Get in REST API, has in the URL the values of resources, e.g if you use the client.Send("GET",url,request), and in request.barcode you have a different value than the URL path, then in the service Get function the request will have the hard-coded value, not the value in URL , as it is the correct. – stefan2410 Sep 17 '13 at 02:30
  • The point of using Send over Get on the client is that you don't have to specify the URL query parameters using Send. That's why Send is the acceptable answer, and not Get. – mariocatch Sep 23 '13 at 02:38
  • No for Restful APIs, in [RESTFul](http://en.wikipedia.org/wiki/Representational_state_transfer), the URI includes the resource unique identifier. If you don't want to specify the URL, then it is not RESTFul. – stefan2410 Sep 23 '13 at 03:02
  • Not sure you're understanding what I'm saying. Send() still uses the URL to place the query parameters... it is still RESTful. From a client perspective, it's much easier to package up a request object and send it off using Send() rather than construct a URL and use Get(). They are BOTH RESTful, one is just nicer from a C# client. – mariocatch Oct 04 '13 at 02:04
  • Try to understand me also, please, if we talk about RESTful, then the Send creates a URL that it is something like order/product?barcode=123, this does not seem RESTFul to me. It should be order/product/123. (this is the URL created by GET, using the Route order/product/{id} By this way the resource is unique according to RESTful architecture. The Send has only a Route of order/product. – stefan2410 Oct 04 '13 at 02:31
  • Moreover, if you use the route in Send("GET", "order/product/123", request), but in request.ID you set 456, then in the service function the request.ID will be 456, not 123. If somebody calls with jQuery/Ajax, the GET, then his result will be inconsistent with the results of C# client. – stefan2410 Oct 04 '13 at 02:35
  • The [URI Template](http://tools.ietf.org/html/rfc6570). We use query parameters in collections. This "/cars?color=blue&type=sedan&doors=4" is Collection URI. this "car/A235678" it is an Element URI and maybe it means the number of my car. [The URIs for Yahoo! REST-based Web services have thefollowingsyntax](http://developer.yahoo.com/social/rest_api_guide/uri-general.html) – stefan2410 Oct 04 '13 at 07:56
  • We just disagree then, no point in arguing over it. The service is still RESTful. It can still be consumed and called through RESTful URLs. You just prefer to complicate your C# client by constructing URLs rather than using the Send() method and passing a request object. Either way, the service is still RESTful. – mariocatch Oct 04 '13 at 14:47
  • Yes we disagree. I could write about the Send function, from the first moment. I will explain you why it is dangerous. (except the rules for the RESTful URI Template) => With GET you can do both , this " order/product?barcode=123" and this "order/product/123" => BUT with Send it is error prone to use the "order/product/123", because if you give in code, different value to reuest.ID, the request will not be consisted with the RESTFul uri. for this reason, I insist, I am not dogmatic. – stefan2410 Oct 04 '13 at 16:00
  • It is better to my opinion, instead Send, to use Get with IReturn (with a minimum dependency if you can), or even Post (that I do for collections with a lot of parameters and when I am not interested for browser cache. – stefan2410 Oct 04 '13 at 16:09
0

Using the Send() method from the JsonServiceClient type is the way to go about doing this.

mariocatch
  • 8,305
  • 8
  • 50
  • 71