Dinindu Perera Dinindu Perera - 2 months ago 23
reST (reStructuredText) Question

C# - Sending and receiving HTTP Requests to REST service

So I'm writing the client side user authentication code for my Web API ReST service.

This is how the request and response should look like and I've written this code to register a user and it works fine.

Http Request:

POST https://localhost:44305/api/Account/Register HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Content-Type: application/json; charset=utf-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:44305/
Content-Length: 84
{"Email":"alice@example.com","Password":"Password1!","ConfirmPassword":"Password1!"}


Http Response:

HTTP/1.1 200 OK
Server: Microsoft-IIS/8.0
Date: Wed, 01 Oct 2014 00:57:58 GMT
Content-Length: 0


Code to accomplish this:

byte[] data = Encoding.UTF8.GetBytes("{\"Email\":\"alssice@example.com\"," + "\"Password\":\"Password1!\"," + "\"ConfirmPassword\":\"Password1!\"}");
WebRequest request = WebRequest.Create("http://localhost:8091/api/Account/Register");
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
request.ContentLength = data.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
string responseContent = null;

using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader sr99 = new StreamReader(stream))
{
responseContent = sr99.ReadToEnd();
}
}
}

Console.WriteLine(responseContent);


This works fine and the user account is created in the database but I don't get the response.

The next problem is sending sending the login details to get a bearer token? How can I do this?

This is what the request and response should look like


HTTP REQUEST FOR AUTHENTICATION:


POST https://localhost:44305/Token HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:44305/
Content-Length: 68

grant_type=password&username=alice%40example.com&password=Password1!


HTTP RESPONSE FOR AUTHENTICATION:

HTTP/1.1 200 OK
Content-Length: 669
Content-Type: application/json;charset=UTF-8
Server: Microsoft-IIS/8.0
Date: Wed, 01 Oct 2014 01:22:36 GMT

{
"access_token":"imSXTs2OqSrGWzsFQhIXziFCO3rF...",
"token_type":"bearer",
"expires_in":1209599,
"userName":"alice@example.com",
".issued":"Wed, 01 Oct 2014 01:22:33 GMT",
".expires":"Wed, 15 Oct 2014 01:22:33 GMT"
}


SO how can I send a request for a token?

Answer

I'd kindly like to suggest you using HttpClient if you're going for your own http rest client in your app.

Solution using HttpClient and Json.net:

public class TokenResponse
{
    public string access_token { get; set; }
    public string token_type { get; set; }
    public int expires_in { get; set; }
    public string userName { get; set; }
    public string issued { get; set; }
    public string expires { get; set; }
}


private async Task Login()
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("https://localhost:44305");
        var content = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("grant_type", "password"),
            new KeyValuePair<string, string>("username", "alice@example.com"),
            new KeyValuePair<string, string>("password", "password1")
        });
        var result = await client.PostAsync("/token", content);
        string resultContent = await result.Content.ReadAsStringAsync();
        var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(resultContent);
    }
}

And if you need to use HttpWebRequest:

If this is the case, your solution might look something like the following.

private void Login()
{
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://localhost:44305/Token");
    request.Method = "POST";
    request.AllowAutoRedirect = false;
    request.Accept = "*/*";
    request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";

    StringBuilder postData = new StringBuilder();
    postData.Append("grant_type=" + HttpUtility.UrlEncode("password") + "&");
    postData.Append("username=" + HttpUtility.UrlEncode("alice@example.com") + "&");
    postData.Append("password=" + HttpUtility.UrlEncode("password"));

    using (StreamWriter stOut = new StreamWriter(request.GetRequestStream(), Encoding.UTF8))
    {
        stOut.Write(postData);
        stOut.Close();
    }
}

Update

Now Im not sure where and how you are trying this. If you're invoking this from a console application main method, make sure the following so you don't have to come back to the same asynchronous context and this should always be invoked from an async method itself:

var result = await client.PostAsync("https://localhost:44305/token", content).ConfigureAwait(false);

I updated my solution in a github gist. It's working for me as it's trying to post the request right away.

Comments