Why use HttpClient for Synchronous Connection

C#asp.netDotnet Httpclient

C# Problem Overview


I am building a class library to interact with an API. I need to call the API and process the XML response. I can see the benefits of using HttpClient for Asynchronous connectivity, but what I am doing is purely synchronous, so I cannot see any significant benefit over using HttpWebRequest.

If anyone can shed any light I would greatly appreciate it. I am not one for using new technology for the sake of it.

C# Solutions


Solution 1 - C#

> but what i am doing is purely synchronous

You could use HttpClient for synchronous requests just fine:

using (var client = new HttpClient())
{
    var response = client.GetAsync("http://google.com").Result;
    
    if (response.IsSuccessStatusCode)
    {
        var responseContent = response.Content; 

        // by calling .Result you are synchronously reading the result
        string responseString = responseContent.ReadAsStringAsync().Result;

        Console.WriteLine(responseString);
    }
}

As far as why you should use HttpClient over WebRequest is concerned, well, HttpClient is the new kid on the block and could contain improvements over the old client.

Solution 2 - C#

I'd re-iterate Donny V. answer and Josh's

> "The only reason I wouldn't use the async version is if I were trying > to support an older version of .NET that does not already have built > in async support."

(and upvote if I had the reputation.)

I can't remember the last time if ever, I was grateful of the fact HttpWebRequest threw exceptions for status codes >= 400. To get around these issues you need to catch the exceptions immediately, and map them to some non-exception response mechanisms in your code...boring, tedious and error prone in itself. Whether it be communicating with a database, or implementing a bespoke web proxy, its 'nearly' always desirable that the Http driver just tell your application code what was returned, and leave it up to you to decide how to behave.

Hence HttpClient is preferable.

Solution 3 - C#

For anyone coming across this now, .NET 5.0 has added a synchronous Send method to HttpClient. https://github.com/dotnet/runtime/pull/34948

The merits as to why where discussed at length here: https://github.com/dotnet/runtime/issues/32125

You can therefore use this instead of SendAsync. For example

public string GetValue()
{
    var client = new HttpClient();
            
    var webRequest = new HttpRequestMessage(HttpMethod.Post, "http://your-api.com")
    {
        Content = new StringContent("{ 'some': 'value' }", Encoding.UTF8, "application/json")
    };

    var response = client.Send(webRequest);

    using var reader = new StreamReader(response.Content.ReadAsStream());
            
    return reader.ReadToEnd();
}

This code is just a simplified example - it's not production ready.

Solution 4 - C#

public static class AsyncHelper  
{
    private static readonly TaskFactory _taskFactory = new
        TaskFactory(CancellationToken.None,
                    TaskCreationOptions.None,
                    TaskContinuationOptions.None,
                    TaskScheduler.Default);

    public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();

    public static void RunSync(Func<Task> func)
        => _taskFactory
            .StartNew(func)
            .Unwrap()
            .GetAwaiter()
            .GetResult();
}

Then

AsyncHelper.RunSync(() => DoAsyncStuff());

if you use that class pass your async method as parameter you can call the async methods from sync methods in a safe way.

it's explained here : https://cpratt.co/async-tips-tricks/

Solution 5 - C#

If you're building a class library, then perhaps the users of your library would like to use your library asynchronously. I think that's the biggest reason right there.

You also don't know how your library is going to be used. Perhaps the users will be processing lots and lots of requests, and doing so asynchronously will help it perform faster and more efficient.

If you can do so simply, try not to put the burden on the users of your library trying to make the flow asynchronous when you can take care of it for them.

The only reason I wouldn't use the async version is if I were trying to support an older version of .NET that does not already have built in async support.

Solution 6 - C#

In my case the accepted answer did not work. I was calling the API from an MVC application which had no async actions.

This is how I managed to make it work:

private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
public static T RunSync<T>(Func<Task<T>> func)
    {           
        CultureInfo cultureUi = CultureInfo.CurrentUICulture;
        CultureInfo culture = CultureInfo.CurrentCulture;
        return _myTaskFactory.StartNew<Task<T>>(delegate
        {
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = cultureUi;
            return func();
        }).Unwrap<T>().GetAwaiter().GetResult();
    }

Then I called it like this:

Helper.RunSync(new Func<Task<ReturnTypeGoesHere>>(async () => await AsyncCallGoesHere(myparameter)));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKetchupView Question on Stackoverflow
Solution 1 - C#Darin DimitrovView Answer on Stackoverflow
Solution 2 - C#trevView Answer on Stackoverflow
Solution 3 - C#alexsView Answer on Stackoverflow
Solution 4 - C#Lean BonaventuraView Answer on Stackoverflow
Solution 5 - C#Josh SmeatonView Answer on Stackoverflow
Solution 6 - C#Jonathan AlfaroView Answer on Stackoverflow