12

I've created a method using the new WebAPI features in MVC4 and have it running on Azure. The method requires that you post a simple LoginModel object that consists of a Username and Password property. Yes, I plan on securing this further once I get past this speed bump :-) The method then responds with an object in Json format:

enter image description here

I can successfully call this method using Fiddler, provided that I include "Content-Type: application/json" in the Request Headers. It returns with 200 and I can go into the Fiddler Inspector and view the Json response object just fine:

enter image description here

I am however having problems calling this same method from a MetroUI app in Windows8 using C#/XAML. I began playing around with the HttpClient and the new Async concepts in C# and no matter how I formatted my Post calls (even when explicitly calling out that I want the Content-Type to be "application/json") Fiddler returns with a 500 error and states that the attempt was using Content-Type:"text/html". I beleive this to be the root of the problem:

enter image description here

I have tried everything conceivable in order to post to this method and get back the Json object, here is my most recent attempt:

HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        HttpContent content = new StringContent(@"{ ""Username"": """ + Username.Text + @", ""Password"": """ + Password.Text + @"""}");

        client.PostAsync("http://myapi.com/authentication", content).ContinueWith(result =>
        {
            var response = result.Result;

            response.EnsureSuccessStatusCode();
        });

This results in a 500 error with Content-Type set to "text/html"

Here was another attempt which also failed:

HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsync("http://myapi.com/authentication", new StringContent(@"{ ""Username"": """ + Username.Text + @", ""Password"": """ + Password.Text + @"""}", Encoding.UTF8, "application/json"));
string statusCode = response.StatusCode.ToString();

Can anyone point me in the right direction?

Just tried the following code thanks to the advice of Nemesv:

HttpClient httpClient = new HttpClient();
        HttpContent content = new StringContent(@"{ ""Username"": """ + Username.Text + @", ""Password"": """ + Password.Text + @"""}");
        content.Headers.ContentType = new MediaTypeHeaderValue("application/json");


        HttpResponseMessage response = await httpClient.PostAsync("http://webapi.com/authentication", content);

        string statusCode = response.StatusCode.ToString();
        response.EnsureSuccessStatusCode();

It now shows "application/json" in my request header, but still shows "text/html" in the Web Session:

enter image description here

INNVTV
  • 3,155
  • 7
  • 37
  • 71

2 Answers2

22

Try this to set the Headers.ContentType:

HttpClient httpClient = new HttpClient();
HttpContent content = new StringContent(@"{ ""Username"": """ + "etc." + @"""}");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = 
    await httpClient.PostAsync("http://myapi.com/authentication", content);
string statusCode = response.StatusCode.ToString();
nemesv
  • 138,284
  • 16
  • 416
  • 359
  • Thanks Nemesv. Just tried that and am still unable to get passed the 500 error, but I do notice that in Fiddler the Header shows that it is using "application/json" - however the web session for the record shows "text/html" I'll attach a screen grab. – INNVTV Mar 26 '12 at 00:21
  • 1
    FYI: see updates at the bottom of my original post. And thank you for your help! – INNVTV Mar 26 '12 at 00:27
  • FYI: I think it is the way I am setting the parameters in my content header. I put a stop in the code and traversed the HttpContent object after setting the StringContent values and could not find the Username or Password items. Do you know of a better method for posting this to the WebAPI? Still looking into it on my end... – INNVTV Mar 26 '12 at 00:33
  • 1
    I did some testing and it works. But I've found that if there are problems in the Json it will fail. E.g you've missed here a `"` : `Username.Text + @""", ""Password"": """`. Anyway you should use a Json serilazer like Json.net and not do it by hand. – nemesv Mar 26 '12 at 08:25
  • Thanks Nemesv! I will implement your suggestions later tonight and let you know! – INNVTV Mar 26 '12 at 19:46
  • @nemesv sorry to hijack this thread, but you had answered a question I had on authorization and I really preferred you answer to the other that I had received. If you could please repost it and that would be awesome! – Jared Jul 12 '12 at 03:48
6

There is some missing try this is working.

UserLoginModel user = new UserLoginModel { Login = "username", Password = "password" };
string json = Newtonsoft.Json.JsonConvert.SerializeObject(user);
HttpContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:1066/api/");
HttpResponseMessage response = client.PostAsync("Authenticate", content).Result;

if (response.IsSuccessStatusCode)
{
  var result = response.Content.ReadAsAsync<ResultModel>().Result;
}
else
{
  return string.Empty;
}
Erwin
  • 4,757
  • 3
  • 31
  • 41
vast
  • 91
  • 1
  • 4
  • This is better, serializing the object with JSON.Net rather than manually building a JsonObject dictionary (which is un-necessary code and would break as soon as the entity changes). In the RTM you can also use the constructor of StringContent to specify the media type and encoding, take UTF8 for example, e.g. var content = new StringContent(json, Encoding.UTF8, "application/json"). – Tony Wall Jan 29 '13 at 14:36