Add CorrelationId to remote calls in ASP.NET MVC5 - c#

I use Delgating handler to add correlation ids to inward requests to my application.
But, my MVC app makes frequent calls to remote domain https://remoteservice.net/xyz via an webapi client provided by them. The remote service API allows users to set correlation id via request header, but the webapi client doesn't provide a way to expose that.
So I am now thinking to set correlation id via owin pipeline for all outgoing remote calls from my MVC app. Is this possible? Any help?

You could extend an HttpClientHandler and add a correlationId header there:
public class CorrelatingHandler : HttpClientHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Add("currelationId", Guid.NewGuid());
return base.SendAsync(request, cancellationToken);
}
}
using(var client = new HttpClient(new CorrelatingHandler())){
.....
}
source: https://forums.asp.net/post/6025521.aspx

Related

The difference between OWIN and IIS on handling HTTP HEAD request when the api is not support the HEAD request

I have a 2 services(WebApi), one is azure cloud service that using IIS host and another one is azure service fabric stateless service that using Owin host. There is a handler that like below, and both services register this handler to handle the context(config.MessageHandlers.Add(new ContextHandler())).
Currently, what I met is: If I call cloud service api(just ping) using HTTP HEAD request, this will return '405 method not allowed'. But if I call fabric service, I will get 'Could not get any response' with 'there was an error connecting to...'.
When debug the code. For the cloud service using IIS, in the below code, the response.Content has no value. But for the fabric service using Owin, the response.Content has value '405 Method not allowed'.
My question is, what the difference between them? Why the Owin will return a response with content back as the request is HEAD request?
Thanks.
public class ContextHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// initialize context
using (new ApiRequestContextWrapper(request))
{
var context = ApiRequestContext.Current;
context.Log.Trace(
$"API Call {request.Method.Method}
{request.RequestUri.GetLeftPart(UriPartial.Path)}");
var response = await base.SendAsync(request,
cancellationToken).ConfigureAwait(false);
return response;
}
}
}

Azure Mobile Services: how to inject custom header into request?

I'm using Azure Mobile Services from within a Xamarin.iOS app.
My service expects a custom header to be sent from the client.
In order to send this, I created my own message handler which I derive from `NativeMessageHandler (part of ModernHttpClient):
this.client = new MobileServiceClient (Constants.ApplicationURL, Constants.GatewayURL, new CustomMessageHandler ());
To get my header in there, the handler looks like this:
public class CustomMessageHandler: NativeMessageHandler
{
protected override Task<System.Net.Http.HttpResponseMessage> SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Headers.Add ("customHeader", "headerValue");
return base.SendAsync (request, cancellationToken);
}
}
The problem is that the header doesn't seem to arrive at the server when my service is deployed to Azure. It works when running it locally in VisualStudio. If I put a breakpoint into my handler, it is hit; so the header really gets added.
Why would it work locally but not on Azure?
And the answer is: D'oh!
I enabled "Authentication" for my Azure App. Hence I would get a 401 for every request. It had nothing to do with my handler. Turned it off and it works like charm.

Any hooks for HttpClient?

When making a REST call, the usual approach with C# is:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:9000/");
client.SendAsync(....);
}
But what if I want every single outbound request to have a custom header, without manual coding? With a WCF proxy I can achieve that result by adding a global endpoint behavior (e.g. IMessageInspector) which will hook every outbound call.
With HttpClient, I don't think such a hook point exists. Perhaps the best I can do is to create an extension method for HttpClient which automatically adds the header. Unfortunately, that means that every developer must still voluntarily comply and remember to manually invoke the extension method.
Any solution I'm overlooking?
p.s. I understand that REST is supposed to be light-weight, and so much of the abstraction of WCF is jettisoned. Still, no harm in asking...
You could use a custom HttpMessageHandler:
public class YourServiceMessageHandler : HttpClientHandler
{
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// Add header to request here
return base.SendAsync(request, cancellationToken);
}
}
And pass it to the HttpClient constructor:
HttpClient client = new HttpClient(new YourServiceMessageHandler());
No hooks like that, but if you are writing a HTTP API, you can just hide the entire uploading process in your class so the users of your API only call something like SendData(dataPackage);, and instead of using HttpRequest in your extension as a parent, you just create an instance of it so others don't see what you are doing.

Remove server header in self hosted WebApi response

We are using a self hosted WebApi and we are required to remove the server header (Server: Microsoft-HTTPAPI/2.0) of the responses sent.
Since it is self hosted, a HttpModule is not an option. Implementing a DelegatingHandler, access to headers as well as adding is possible. The asp.net website nicely details how one can do that.
But the server header seems to be added much later in the pipeline since it is not set in the HttpResponseMessage we return from the DelegatingHandler. However, we are able to add values.
async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
response.Headers.Server.Add(new ProductInfoHeaderValue("TestProduct", "1.0"));
response.Headers.Add("Server", "TestServerHeader");
return response;
}
Both Server.Add and .Add work as expected. response.Headers.Remove("Server"); however does not work, because the server header is not set, response.Headers.Server is empty.
Is there anything i am missing?
There is no code solution to remove Server HTTP header on self host.
The only solution is to edit windows registry:
https://learn.microsoft.com/ru-ru/archive/blogs/dsnotes/wswcf-remove-server-header
add
appBuilder.Use((context, next) =>
{
context.Response.Headers.Remove("Server");
context.Response.Headers.Add("Server", new[] { "" });
return next.Invoke();
});
to Startup Configuration method just before
config.EnsureInitialized();

Web API response time

I'm building a server monitoring system and want to send a request to a Web API and get the server's health in a JSON object if it's ok, if its database connections are working, its response time, etc.
How can I implement the response time, saying how long the Web API takes to answer the request?
If you want to implement Web Api Monitoring, you can create a custom DelegatingHandler to track action duration and status.
Here is a very basic example to measure operation duration. The duration is added to response (quite useless) ; it's better to store this kind of data to a dedicated repository.
public class MonitoringDelegate : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
var watcher = Stopwatch.StartNew();
var response = await base.SendAsync(request, cancellationToken);
watcher.Stop();
//store duration somewheren here in the response header
response.Headers.Add("X-Duration", watcher.ElapsedMilliseconds.ToString());
return response;
}
}
You could start a Stopwatch on your client and stop it when you recive your awnser

Categories