Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactor HttpWebRequest to HttpClient?

Tags:

c#

How would I convert this to HttpClient? What I'm looking to do is submit a Tweet to the Twitter api and get the response as Json. The HttpWebRequest is working fine but I just want to port it to HttpClient. I made an attempt at it in the second code example, but it's not actually sending or receiving the response.

HttpWebRequest request = null;
WebResponse response = null;
string responseCode = String.Empty;
try
{
    string postBody = "status=" + EncodingUtils.UrlEncode(status);

    request = (HttpWebRequest)HttpWebRequest.Create(resource_url);        
    request.ServicePoint.Expect100Continue = true;
    request.UseDefaultCredentials = true;
    request.PreAuthenticate = true;
    request.Credentials = CredentialCache.DefaultCredentials;
    request.ServicePoint.ConnectionLimit = 1;
    request.Headers.Add("Authorization", authHeader);
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";

    using (Stream stream = request.GetRequestStream())
    {
        using (StreamWriter writer = new StreamWriter(stream))
        {                       
            writer.Write(postBody);
        }
    }
    using (response = request.GetResponse())
    {
        response.ContentType = "application/json";
        responseCode = ((HttpWebResponse)response).StatusCode.ToString();
    }
}
catch (WebException ex)
{
    if (ex.Status != WebExceptionStatus.NameResolutionFailure)
    {
        request.Abort();
        request = null;
    }
    throw ex;
}
return responseCode;

This is what I've tried to get it work:

private async Task<string> MakeWebRequest1(string status, string resource_url, string authHeader)
    {
        HttpClientHandler clientHandler = new HttpClientHandler();
        clientHandler.Credentials = CredentialCache.DefaultCredentials;
        clientHandler.PreAuthenticate = true;
        clientHandler.AllowAutoRedirect = true;
        string responseCode = "";
        string postBody = "status=" + EncodingUtils.UrlEncode(status);
        var request = new HttpRequestMessage()
        {
            RequestUri = new Uri(resource_url),
            Method = HttpMethod.Post,

        };
        request.Headers.Add("Authorization", authHeader);
       // request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
        request.Content = new StringContent(postBody, Encoding.UTF8,"application/x-www-form-urlencoded");//CONTENT-TYPE header

        using (HttpClient client = new HttpClient(clientHandler))
        {
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
            //  Stream stuff = await client.GetStreamAsync(resource_url);
            using (HttpResponseMessage response = await client.SendAsync(request))
            {
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                if(response.StatusCode == HttpStatusCode.OK)
                {
                    responseCode = "OK";
                }
            }
        }
        clientHandler.Dispose();
        return responseCode;
    }
enter code here

I've tried to add another parameter to the request and it's always coming back as 401 unauthorized. I'm trying to create a Twitter thread. If I remove the in_reply_to_status_id then it's fine.

data = new Dictionary<string, string> {
      ["status"] = "@username + status,
      ["in_reply_to_status_id"] = "1167588690929115136"
};

The Twitter API describes it here https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update

like image 807
Charles Owen Avatar asked Aug 24 '19 03:08

Charles Owen


People also ask

Does HttpWebRequest use HttpClient?

HttpClient combines the flexibility of HttpWebRequest and WebClient. To start, we use the async and await keywords. HttpClient doesn't support FTP, mocking and testing HttpClient is easier.

What is HttpWebRequest C#?

The HttpWebRequest class provides support for the properties and methods defined in WebRequest and for additional properties and methods that enable the user to interact directly with servers using HTTP.

Which is better HttpClient or WebClient?

In essence, HttpClient combines the flexibility of HttpWebRequest and the simplicity of WebClient, giving you the best of both the worlds. The HttpWebRequest class provides a lot of control over the request/response object.


1 Answers

Reference You're using HttpClient wrong to understand why a static client is being used.

static Lazy<HttpClient> client = new Lazy<HttpClient>(() => {
    HttpClientHandler clientHandler = new HttpClientHandler {
        Credentials = CredentialCache.DefaultCredentials,
        PreAuthenticate = true,
        AllowAutoRedirect = true
    };
    return new HttpClient(clientHandler);
});

private async Task<string> PostStatusRequestAsync(string status, string resource_url, string authHeader) {
    using (var request = new HttpRequestMessage(HttpMethod.Post, resource_url)) {
        request.Headers.TryAddWithoutValidation("Authorization", authHeader);
        request.Headers.Accept.Clear();
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var data = new Dictionary<string, string> {
            ["status"] = status
        };

        request.Content = new FormUrlEncodedContent(data);

        using (HttpResponseMessage response = await client.Value.SendAsync(request)) {
            return response.StatusCode.ToString();
        }
    }
}

Note the use of the FormUrlEncodedContent for the request body, which will encode and concatenate the data as well as take care of the mime type header

...but it's not actually sending or receiving the response.

Ensure that the above is not invoked as a synchronous blocking call, like .Result, which could cause a deadlock.

For example, an async event handler can be used to make the async call

public async void onButtonClick(object sender, EventArgs args) {
    //Non-blocking call
    var tweetRequestCode = await PostStatusRequestAsync(TweetText, AuthUtils.GetResourceUrl(), AuthUtils.GetWebRequestHeader())); 

    //back on UI thread
    //...
}

Reference Async/Await - Best Practices in Asynchronous Programming

like image 72
Nkosi Avatar answered Nov 11 '22 08:11

Nkosi