7

RestSharp seems to not allow me to override the Content-Type for a post request. I've followed the directions found here to no avail. I've also tried manually setting the header content type to application/json via request.AddHeaders("content-type", "application/json");

Examples of the request execution:

private IRestResponse ExecuteRequest<T>(string resource, Method method, T model)
{
    var client = CreateRestClient();
    var request = new RestRequest(resource, method) 
    { 
        RequestFormat = DataFormat.Json 
    };
    var json = JsonConvert.SerializeObject(model);

    request.AddHeader("Accept", "application/json");
    request.AddHeader("User-Agent", "Fiddler");
    request.Parameters.Clear();
    request.AddParameter("auth_token", _apiKey);
    request.AddParameter("application/json", json, ParameteType.RequestBody);

    return client.Execute(request); 
}

The response error message:

{
  "error": {
  "code": 400,
  "message": "The request requires a properly encoded body with the 'content-type' header set to '['application/json']",
  "type": "Bad Request" }
}

Fiddler request raw data:

POST  **omitted** HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json,text/javascript, text/xml
User-Agent: RestSharp/105.0.1.0
Content-Type: application/x-www-form-urlencoded
Host: **omitted**
Content-Length: 51
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

As you can see, the request Content-Type is still application/x-www-form-urlencoded. Any ideas? (thanks in advance)

user692942
  • 16,398
  • 7
  • 76
  • 175
Vincent Johnson
  • 196
  • 1
  • 1
  • 7

2 Answers2

10

It appears this is a misunderstanding of how RestSharp interprets parameters for post requests. From John Sheehan's post on the google group:

If it's a GET request, you can't have a request body and AddParameter adds values to the URL querystring. If it's a POST you can't include a POST parameter and a serialized request body since they occupy the same space. You could do a multipart POST body but this is not very common. Unfortunately if you're making a POST the only way to set the URL querystring value is through either string concatenation or UrlSegments:

var key = "12345";
var request = new RestRequest("api?key=" + key);
// or
var request = new RestRequest("api?key={key});
request.AddUrlSegment("key", "12345");

My revised Execute request method that now works looks like this:

private IRestResponse ExecuteRequestAsPost<T>(T model, string resource, Method method)
{
    resource += "?auth_token={token}";
    var client = CreateRestClient();
    var request = new RestRequest(resource, method) { RequestFormat = DataFormat.Json };
    var json = JsonConvert.SerializeObject(model);
    request.AddHeader("User-Agent", "Fiddler");

    request.AddUrlSegment("token", _apiKey);
    request.AddParameter("application/json", json, ParameterType.RequestBody);

    return client.Execute(request);
}
Vincent Johnson
  • 196
  • 1
  • 1
  • 7
  • 1
    Thank you, this worked for me. The key change here that did it for me was how you did request.addParameter(). – Harris Dec 04 '15 at 21:09
2

It sounds like you may have figured it out, but if you're interested in an alternative, one of my goals in writing Flurl was to be more explicit about where you want to put your parameters but still do it with less code. In this case, the entire request would look something like this:

var response = await baseUrl
    .AppendPathSegment(resource)
    .SetQueryParam("auth_token", _apiKey)
    .WithHeader("User-Agent", "Fiddler")
    .PostJsonAsync(model);
Todd Menier
  • 37,557
  • 17
  • 150
  • 173
  • Interesting, I'll take a look! – Vincent Johnson Feb 18 '15 at 17:35
  • 1
    Hmm... *"As of Flurl.Http 0.4, instances of the underlying HttpClient are disposed immediately after each HTTP call by default"*. This isn't how `HttpClient` is designed to work. See [A: What is the overhead of creating a new HttpClient per call in a WebAPI client?](http://stackoverflow.com/a/22561368/692942) – user692942 Oct 28 '16 at 09:08