'ServicePointManager.FindServicePoint(Uri)' is obsolete: Use HttpClient instead - httpclient

Started getting this error after updating C# upgraded from NET 5 to 6-
Warning SYSLIB0014 'ServicePointManager.FindServicePoint(Uri)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.'
var servicePoint = ServicePointManager.FindServicePoint(requestUri.GetEndpoint());
if (servicePoint.ConnectionLeaseTimeout == -1){}

On the Networking of the Breaking changes in .NET 6 there's WebRequest, WebClient, and ServicePoint are obsolete:
WebRequest, WebClient, and ServicePoint are obsolete
xref:System.Net.WebRequest, xref:System.Net.WebClient, and xref:System.Net.ServicePoint classes are marked as obsolete and generate a SYSLIB0014 warning at compile time.
Version introduced
6.0
Change description
WebRequest, WebClient, and ServicePoint classes were added to .NET Core in version 2.0 for backward compatibility. However, they introduced several runtime breaking changes, for example, WebRequest.GetRequestStream allocates memory for the whole response, and WebClient.CancelAsync doesn't always cancel immediately.
Starting in .NET 6, the WebRequest, WebClient, and ServicePoint classes are deprecated. The classes are still available, but they're not recommended for new development. To reduce the number of analyzer warnings, only construction methods are decorated with the ObsoleteAttribute attribute.
Recommended action
Use the System.Net.Http.HttpClient class instead.
For FTP, since HttpClient doesn't support it, we recommend using a third-party library.
Affected APIs
WebRequest
HttpWebRequest
FtpWebRequest
WebClient
ServicePoint

We can replace ServicePointManager.FindServicePoint with SocketsHttpHandler as this example:
In .NET Framework
httpClient = new HttpClient();
ServicePointManager.FindServicePoint(new Uri(_baseAddress)).ConnectionLeaseTimeout = 5 * 60 * 1000;
In .NET Core
var socketsHttpHandler = new SocketsHttpHandler()
{
PooledConnectionLifetime = TimeSpan.FromMinutes(5),
};
httpClient = new HttpClient(socketsHttpHandler)
{
BaseAddress = new Uri(_baseAddress)
};
In detail, you can take a look at this article: https://makolyte.com/csharp-configuring-how-long-an-httpclient-connection-will-stay-open/

Related

is there a way to mock internal service calls while writing Component testcases

I'm writing my component level test-cases for my repository. My API calls internally a third party API which I need to mock. I don't have direct access to that API neither I can directly call it, it needs to be called from within the API calls. I need to mock in order to run the component test-cases successfully. I tried wiremock but looks like it is not working and my API is still calling the 3rd party URL. Is there any way to solve this problem. Here is my code -
Annotation at class level
#Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8888));
WireMockServer wm;
Started server
#BeforeEach
void setUp() {
wm = new WireMockServer(WireMockConfiguration.options().port(8888));
wm.start();
}
In the tests.
wireMockServer.start();
wm.stubFor(get("https://someurl")
.willReturn(badRequest()
.withHeader("Content-Type", "application/json")
.withBody("<response>SUCCESS</response>")));
MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders
.post(apiContextPath)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(gson.toJson(offerParams)))
.andExpect(status().isOk()).andReturn();
wireMockServer.stop();
Sorry can't paste whole code due to security reasons.
It looks like you're trying to use the JUnit 4 rule with JUnit 5, meaning the WireMock server won't be started.
Try the JUnit Jupiter extension instead: https://wiremock.org/docs/junit-jupiter/

Autofac IContainer and DiagnosticTracer for ASP .Net 5

How I can get IContainer instance for my ASP.Net 5 app?
I need to enable diagnostics, and based on official documentation SubscribeToDiagnostics method is accessible only from IContainer, and ASP Net Core 3+ Integration this.AutofacContainer = app.ApplicationServices.GetAutofacRoot(); exposes only ILifetimeScope.
I have also noticed that Autofac supports DiagnosticListener - is this a way how I should trace for informations?
Does Autofac provide build in formatters for example for RequestDiagnosticData?
What are your recommendations?
I've updated the ASP.NET Core 3 example for Autofac to show how this works. The secret is using a build callback.
In your ConfigureContainer method, you register a callback to subscribe to diagnostics.
public void ConfigureContainer(ContainerBuilder builder)
{
// Add any Autofac modules or registrations, then...
//
// If you want to enable diagnostics, you can do that via a build
// callback. Diagnostics aren't free, so you shouldn't just do this
// by default. Note: since you're diagnosing the container you can't
// ALSO resolve the logger to which the diagnostics get written, so
// writing directly to the log destination is the way to go.
var tracer = new DefaultDiagnosticTracer();
tracer.OperationCompleted += (sender, args) =>
{
Console.WriteLine(args.TraceContent);
};
builder.RegisterBuildCallback(c =>
{
var container = c as IContainer;
container.SubscribeToDiagnostics(tracer);
});
}

Issue with HttpClient in AEM

I have an HttpClient code written that is from org.apache.commons.httpclient package.
In that I am setting connection time and socket time out this way.
final HttpClient http = new HttpClient(this.connectionManager);
http.getParams().setParameter("http.connection.timeout", this.connectionTimeout);
http.getParams().setParameter("http.socket.timeout", this.socketTimeout);
Now the Adobe Cloud has raised issue that timeout is not being set(which is not true).
They suggested to set timeouts using
#Reference
private HttpClientBuilderFactory httpClientBuilderFactory;
public void doThis() {
HttpClientBuilder builder = httpClientBuilderFactory.newBuilder();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000)
.setSocketTimeout(5000)
.build();
builder.setDefaultRequestConfig(requestConfig);
HttpClient httpClient = builder.build();
// do something with the client
}
Refer Link
But HttpClientBuilderFactory does not belong to **org.apache.commons.httpclient it belongs to org.apache.http.client**
And always returns Closable Http client.
How do I resolve this security issue? Can I add an annotation for exception? Or will I have to rewrite all my code?
This issue is with Adobe Experience Manager 6.5 instance.
Is it probably because you are not setting the right timeout parameter?
You are setting the property http.connection.timeout which is not available in the class org.apache.commons.httpclient.params.HttpClientParams.
http.getParams() returns an instance of HttpClientParams which has the socket timeout and connection manager timeout but not a connection timeout. You could probably use the constant HttpClientParams.CONNECTION_MANAGER_TIMEOUT to set a timeout for the connection manager?
On the other hand, the property http.connection.timeout is available for the class HttpConnectionParams.
Constant field values reference
The problem is Adobe has two versions of HttpClient the old 3.x that has package structure org.apache.commons.httpclient.HttpClient and the one that HttpClientBuilderFactory gives out that is 4.x org.apache.http.Httpclient.
I was breaking my head around this. Finally we were left with two options...
1) Rewrite all our commons http api(3.x) to the newer version of apache.http (4.x) that has the methods setTimeout and setConnectionTimeout
OR
2)#SuppressWarnings("CQRules:ConnectionTimeoutMechanism")
We chose Option number 2 as the effort arround this was huge and we are planning to go live soon.

Auto-generating a WebRequest

I am trying to consume a binary stream from a ServiceStack service, as described here:
How to consume a file with a ServiceStack client
I realize that I must use a custom WebClient, since I want direct access to the response stream. However, I would still like to avoid making this client by hand. Instead, I'd like to write something like,
var webClient = new JsonServiceClient(baseUrl)
.ConfigureWebClient(new MyRequestDto { Foo = "bar" }));
This way, I wouldn't have to assemble the URL and query string by hand; and when I change my request DTO, I wouldn't have to remember to change my custom WebClient setup code, either.
Is there a way to accomplish this, somehow ? I've looked at ServiceClientBase.PrepareWebRequest(...), and it does a whole lot of useful stuff that I don't feel like copy/pasting into my own code. I'd love to inherit ServiceClientBase and call that method directly, but it's private, so I can't. Anyone got any other ideas ?
All of ServiceStack's C# Service Clients have both a Global and a Local Request Filter allowing you to initialise the Request and Global and Local Response Filters allowing fine-grained access to the returned HttpWebResponse.
Initializing the WebRequest of all ServiceClients using a Global Request Filter:
ServiceClientBase.HttpWebRequestFilter = httpReq => ConfigureWebClient(httpReq);
Using the Local Request Filter:
var client = new JsonServiceClient(baseUrl) {
LocalHttpWebRequestFilter = httpReq => ConfigureWebClient(httpReq)
};
Although if you just want the binary response All Service Clients allow you to specify either a string, byte[], Stream or HttpWebResponse as your Generic Response type and it will return what was requested. See the Service Client wiki page for more examples of these.
Here's how you can retrieve binary responses:
byte[] responseBytes = client.Get<byte[]>("/poco/World");
var dto = responseBytes.FromUtf8Bytes().FromJson<PocoResponse>();
Or with a Stream:
using (Stream responseStream = client.Get<Stream>("/poco/World")) {
var dto = responseStream.ReadFully().FromUtf8Bytes().FromJson<PocoResponse>();
}
Or from the underlying HttpWebResponse:
HttpWebResponse webResponse = client.Get<HttpWebResponse>("/poco/World");
using (var stream = webResponse.GetResponseStream())
using (var sr = new StreamReader(stream)) {
var dto = sr.ReadToEnd().FromJson<PocoResponse>();
}
You can change Open Source Software, you don't have to work around it
ServiceStack is Open Source software, there's no need to look for hacks or try to work around something that's not accessible or not available, make a pull-request to change what you want and if it's a valid request for a common use-case it will likely be accepted. Otherwise feel free to take a fork of the Source code and customize it as you wish.

web api XmlMediaTypeFormatter exception

I want to use IoC / the dependency resolver of the web api framework for decoupling.
The XmlFormatter cant serialize interfaces,... Ok. But what would be the purpose of IoC and the DependencyResolver if I cant return xml?
I cant even do this:
(Method in my ApiController)
public HttpResponseMessage Get()
{
IEnumerable<Project> projects = new List<IProject>() { new Project(), new Project() }.Select(p => p as Project);
HttpResponseMessage response = Request.CreateResponse<IEnumerable<Project>>(HttpStatusCode.OK, projects);
return response;
}
I create a list of IProjects and cast them to 'Project'. But while creating the response I get this:
The configured formatter
'System.Web.Http.Tracing.Tracers.XmlMediaTypeFormatterTracer' cannot
write an object of type 'WhereSelectListIterator`2'.
That is a XmlMediaTypeFormatterTracer? I dont want tracing that throws errors while serialization. (BTW: I replaced the standard XMLformatter with my own one. However "XmlMediaTypeFormatterTracer" throws the exception...
Info: I get the same error while using the standard formatter)
Why is this XmlMediaTypeFormatterTracer called even if I implement my own xmlformatter?
my problem solved with
config.Formatters.XmlFormatter.UseXmlSerializer = false;
Have you enabled Tracing in your application? If yes, the Tracing logic wraps formatters into its a wrapper tracer formatters.