How to instantiate HttpClient in windows form correctly - asp.net-web-api2

As per MSDN
HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors. Below is an example using HttpClient correctly.
public class GoodController : ApiController
{
private static readonly HttpClient HttpClient;
static GoodController()
{
HttpClient = new HttpClient();
}
}
But in windows form (obviously controller doen't make sense here) , how to manage HttpClient in desktop application correctly, each instance of HttpClient opens a port on the server , so obviously multiple instances would not be good.

Related

Resharp DI and DNS resolution

I'm upgrading to version 107 restsharp and i'm wondering if both these options below are ok ways of doing dependency injection in dotnet with restsharp.
The documents say don't create a new restsharp for every request (connection pool exhaustion resaons) but if the httpclient is injected via the constructor will I be get the benefit of DNS resolution changes even though rest client is contained in transient scoped object (i think that's what AddHttpClient will do). I know there will be some price to pay for creating a transient object, but for a general purpose business app maybe that's fine?
Recommended way as described in the documentation
services.AddSingleton<IMyClient, MyClient>();
public class MyClient : IMyClient
{
protected readonly RestClient _restClient;
public MyClient()
{
_restClient = new RestClient();
}
}
OR: is it ok to do this?
services.AddHttpClient<IMyClient, MyClient>();
public class MyClient : IMyClient
{
protected readonly RestClient _restClient;
public MyClient(HttpClient httpClient)
{
_restClient = new RestClient(httpClient);
}
}
You should AddSingleton, not AddHttpClient as per official documentation:
https://restsharp.dev/v107/#restclient-lifecycle
If you use a dependency-injection container, register your API client as a singleton.
I believe it's becouse RestClient is managing the connection pools and addressing known issues, that AddHttpClient would typically address.
If you would use HttpClient directly, you should follow Microsofts recommendations from below URL, where you have a choice of Singleton or AddHttpClient:
https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines#recommended-use
Also, not sure how your 2nd option works at this point.
Also, great video explaining more about what AddHttpClient does (sets HttpClient as Transient etc):
https://www.youtube.com/watch?v=Z6Y2adsMnAA&t=335s

An injectable class needs to read http headers prior to being injected into other class constructors

Is it possible to read http header keys and provide them in a service class to be used by injection to other services.
In startup.cs - I know this happens before the request is materialized, therefore HttpContext is null.
services.AddScoped<IMyConfigurationService>(provider =>
{
string theKey = new HttpContextAccessor().HttpContext?.Request?.Headers["TheKey"].ToString();
return new MyConfigurationService(theKey);
});
In ClassA
public MyCommandDirector(
IMyConfigurationService myConfiguration)
//IHttpContextAccessor httpContext) //<-- Can not do this. This library is shared in legacy apps.
{
...
}
The library is shared across different technologies and IHttpContextAccessor is not available in legacy win forms app. Is there another way I can inject a configuration class that has already read keys in the http header prior to injection in web api 2.0 .net core?

Resolving dependencies in Integration test in ASP.NET Core

I have ASP.NET Core API. I have already gone through documentation here that shows how to do integration testing in asp.net core. The example sets up a test server and then invoke controller method.
However I want to test a particular class method directly (not a controller method)? For example:
public class MyService : IMyService
{
private readonly DbContext _dbContext;
public MyService(DbContext dbContext)
{
_dbContext = dbContext;
}
public void DoSomething()
{
//do something here
}
}
When the test starts I want startup.cs to be called so all the dependencies will get register. (like dbcontext) but I am not sure in integration test how do I resolve IMyService?
Note: The reason I want to test DoSomething() method directly because this method will not get invoked by any controller. I am using Hangfire inside this API for background processing. The Hangfire's background processing job will call DoSomething() method. So for integration test I want to avoid using Hangfire and just directly call DoSomething() method
You already have a TestServer when you run integration tests, from here you can easily access the application wide container. You can't access the RequestServices for obvious reason (it's only available in HttpContext, which is created once per request).
var testServer = new TestServer(new WebHostBuilder()
.UseStartup<Startup>()
.UseEnvironment("DevelopmentOrTestingOrWhateverElse"));
var myService = testServer.Host.Services.GetRequiredService<IMyService>();

Limit connection in RESTful web service

Is there a way to configure a rest web service to allow only one connection at a time?
I am using Wildfly 9.0.1-Final with the resteasy 3.0.11.Final implementation.
You can use synchronized block on static field:
private static final Object LOCK = new Object();
#GET
#Path("find")
#Produces(MediaType.APPLICATION_JSON)
public Response find(){
synchronized(LOCK){
//your code
}
}

Calling WebClient within WebService

I started developing an application in Silverlight that was dealing with downloading the HTML of a website and then parsing it. With Silverlight 4 this can be achieved easily by simply requesting elevated permissions. With Silverlight 3, however, the only way to get the HTML of a website is via a WebService call. My initial idea was to do the following:
public class Service1
{
[OperationContract]
public void GetHtml()
{
Uri targetUri = new Uri("http://www.google.com", UriKind.RelativeOrAbsolute);
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += this.WebClient_DownloadStringCompleted;
webClient.DownloadStringAsync(targetUri);
}
private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
}
}
However, I realized that as soon as I make the call, which is async as well, from my Silverlight application, there is no way for me to retrieve the HTML of the website. That is why I changed to the following:
public class Service1
{
[OperationContract]
public string GetHtml()
{
Uri targetUri = new Uri("http://www.google.com", UriKind.RelativeOrAbsolute);
WebClient webClient = new WebClient();
return webClient.DownloadString(targetUri);
}
}
I believe the last approach is not that fine since it will freeze the thread. So, my question, is there a way to achieve the first approach a.k.a. make async call from an async call :). Any help would be greatly appreciated.
Best Regards,
Kiril
You can achieve your goal by implementig a Duplex Service. There is some useful information about it on the msdn site and a wonderful podcast entry by Mike Taulty. In general, you would have to modify your operation contract by splitting it into two parts. First part would initiate your WebClient download on the server. Then, on the server, after the html has been downloaded, the server would call back a contract that is implemented on the client side with the payload consisting of the required html content.