Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RestSharp defaulting Content-Type to application/x-www-form-urlencoded on POST

Tags:

c#

restsharp

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)

like image 941
Vincent Johnson Avatar asked Feb 15 '15 23:02

Vincent Johnson


2 Answers

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);
}
like image 144
Vincent Johnson Avatar answered Sep 21 '22 07:09

Vincent Johnson


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);
like image 27
Todd Menier Avatar answered Sep 20 '22 07:09

Todd Menier