2

I'm using the latest ServiceStack client lib in a .Net project and I'm having some issue making a PUT request. Especially it doesn't seem to take into account the type of parameter defined in the RequestDto object and put all params in the body (despite the param being defined as type ="query").

My Request object (auto-generated) looks like this:

[Route("/test/name", "PUT")]
public partial class PutTestName
: IReturn<PutTestNameResponse>
{
    ///<summary>
    ///the user id
    ///</summary>
    [ApiMember(Description = "the user id", ParameterType = "query")]
    public virtual string UserId { get; set; }

    ///<summary>
    ///the name
    ///</summary>
    [ApiMember(Description = "the name", ParameterType = "query")]
    public virtual string Name { get; set; }

}

I make the call like this:

_apiClient.Put(new PutTestName(){UserId ="xyz..", Name="Bob"});

and I get "Resource not found" exception in return.

When I run the query manually using Postman (and putting both parameters in the Querystring) it works ok.

When debugging the C# client with fiddler I can see that no parameter is set to the query string and they are both passed in the body.

Edit: This what the Fiddler Request Raw looks like:

PUT https://xxxx/test/name HTTP/1.1
User-Agent: ServiceStack .NET Client 4.56
Accept-Encoding: gzip,deflate
Ocp-Apim-Subscription-Key: 783....
Content-Encoding: gzip
Accept: application/json
Content-Type: application/json
Host: xxx.net
Content-Length: 115
Expect: 100-continue
Connection: Keep-Alive

{"UserId":"xxx","Name":"Bob"}

There is Azure API Management between the ServiceStack API and my call but I don't think this is the issue. The client code is setting the parameters in the body while they're supposed to be in the query.

Etienne
  • 1,058
  • 11
  • 22

1 Answers1

2

If the same request works with POST then it's likely that WebDav is enabled and interfering with your PUT Request in which case you should disable WebDav so the request can reach ServiceStack unimpeded.

For debugging HTTP Interoperability issues like this, you should inspect (and provide here) the Raw HTTP Response Headers using a tool like Fiddler, Chrome Web Inspector or WireShark. If the HTTP Response Headers doesn't include an X-Powered-By: ServiceStack.. Header than it's likely the request has been intercepted and blocked before it reaches ServiceStack, e.g. IIS/ASP.NET or a forwarding proxy.

The client code is setting the parameters in the body while they're supposed to be in the query.

ServiceStack only sends parameters in the body for HTTP Verbs that don't have a request body like GET or DELETE, for Verbs with Request bodies, e.g. POST or PUT ServiceStack's JsonServiceClient will POST JSON as expected.

ServiceStack Services will accept parameters posted in either QueryString, JSON Request Body or x-www-form-urlencoded Content-Type. If you're not calling a ServiceStack Service you should be using a generic HTTP Client like HTTP Utils which will allow you to control exactly how the Request is sent, e.g:

var response = absoluteUrl.ToPutUrl(new PutTestName {...});

Will send the results as x-www-form-urlencoded.

ServiceStack's .NET Service Clients are only for sending requests to ServiceStack Services.

Community
  • 1
  • 1
mythz
  • 141,670
  • 29
  • 246
  • 390
  • @Etienne You've only added the HTTP Request Headers, what's the HTTP Response Header look like? – mythz Mar 21 '17 at 03:16
  • I don't think it matters here, if I make the same request using PostMan and putting the param in the query I get a correct result. If I put them in the body I get 404. Am I missing something ? – Etienne Mar 21 '17 at 03:19
  • @Etienne If this is not a ServiceStack Service you shouldn't be using ServiceStack's `JsonServiceClient`. You can use a generic HTTP Client like [HTTP Utils](http://docs.servicestack.net/http-utils#posting-data). – mythz Mar 21 '17 at 03:24
  • It's indeed not a ServiceStack (Could a ServiceStack live behind Azure API Management btw ?) my bad thanks a lot – Etienne Mar 21 '17 at 04:03
  • @Etienne Keep an eye out for next v4.5.8 release for AutoRest/Azure API Management support :) – mythz Mar 21 '17 at 04:25
  • I'm unfortunately not in control of how the API is built and coded and I'm extremely confused to say the least. I know our vendor has built the API using serviceStack and only recently they've added Azure APIM. In my understanding I thought that Azure APIM was simply a gateway/frontend layer for an existing API to give you auditing/security/Azure stuff. So I thought the backend would still be ServiceStack and that it would not change anything for my client code. I'm sure I would have had no trouble is those param were set as body params. I'm gonna use your Http Utils extension for now. Thx – Etienne Mar 21 '17 at 05:03
  • @Etienne I can't see anything from here to know for sure what's going on, but calling the ServiceStack Services directly with the `JsonServiceClient` would've just worked. From what you're saying it suggests APIM is blocking valid ServiceStack requests in which case you should consult the vendor and ask them which C# HTTP Client you should be using instead, e.g. they may have generated one from a hand-rolled API spec that they're using to configure their API to work with APIM. – mythz Mar 21 '17 at 05:12
  • That's the thing, in my understanding, the request is not valid (when sent from JsonServiceClient), because the server excepts the param in the URL and they end up in the body hence the 404. And this is not related to the API sitting behind Azure APIM or not. Had this endpoint been defined with body param instead of query it would work just fine. At least this is what I can see. I'm going to use extension method for this call for now and have a chat with the vendor. Thanks again – Etienne Mar 21 '17 at 05:28