How best to inject async client/request configuration into NSwag client code - c#

We are using NSwag generated client code for a web API. The API requires an Authorization header to be set on all requests.
This header value needs to be generated from async library methods (ITokenAcquisition.GetAccessTokenForUserAsync() in case it matters).
So far the best option we've come up with is to create a class that implements
public Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
HttpCompletionOption completionOption,
CancellationToken cancellationToken)
wrapping an HTTPClient, which would allow us to get the token and set the header before calling SendAsync on the wrapped HttpClient. We can then inject that class as the HttpClient used by the NSwag code.
I don't think we can use NSwag's CreateHttpClientAsync because I can't see how to inject the ITokenAcquisition (and other dependencies) into the base class. (Unless the client generation code is cleverer than I'm giving it credit for)
Have we missed something?

The best solution we came up with doesn't actually use any NSwag customisation in the end.
Instead we added a class inheriting from DelegatingHandler and overrode SendAsync there.
We then added our DelegatingHandler to the HttpClient passed to the NSwag client. e.g. during service registration:
services.AddHttpClient<NSwagClientInterface, NSwagClientImplementation>((provider, client) =>
{
client.BaseAddress = new Uri(Configuration["BaseAddress"]);
})
.AddHttpMessageHandler<MyDelegatingHandler>();

Related

AddScoped dependency with a CancellationToke

I have a .NET core dependency that is scoped to each REST API request. It is added in Startup.ConfigureServices with a call to AddScoped.
I want to add cancellation support to this. If I add a CancellationToken cancellationToken to any controller action's parameters I can get a token that is cancelled if the client-side request is. I can then pass that token to all the methods on my dependency.
However, the dependency is scoped to the request, so passing the token down through the action to the methods feels unnecessary - could I just add the CancellationToken to the scoped dependency somehow?
could I just add the CancellationToken to the scoped dependency somehow?
Well, technically yes. i.e. by injecting IHttpAccessorand accessing HttpContext.RequestAborted property, which is the same cancellation token you usually get passed into the controllers action if defined.
But using the action parameter overload is actually kinda discouraged as in every controller action you can access the cancellation token via HttpContext.RequestAborted and having it in controllers action kinda makes the token public, i.e. when creating Swagger scheme (at least was the case back in 2017), where as using the HttpContext itself didn't expose it to the public.
The only exception to that seems to be, when using "Poco Controllers" which don't inherit from Controller or ControllerBase and not injecting IHttpAccessor into this controller.
But injecting cancellation tokens into arbitrary services is problematic as you get a hard dependency on the web framework (IHttpAccessor/HttpContext).
It's best and cleanest to keep having a CancellationToken parameter on your methods which can be cancelled in a meaningful way and make the token optional, so you can only pass the parameter in situation where you have a request or a situation that can be cancelled
public Task<Result> ProcessSomething(string param1, CancellationToken cancellationToken = default)
{
}

Invoke method/Do action before every POST/GET request .NET Core

What I am trying to achieve - My application is simply ASP .Net Core application. It is not Web API. I want to execute method before every post/get request from my app to external sources, for example:
I am sending a post request, to check SSL expiry date to some website API and it returns me a response. According to the response I am sending another request or not. I don't want to place call method statement before every request, I would like to do it globally.
I was trying to achieve this based on http://www.sulhome.com/blog/10/log-asp-net-core-request-and-response-using-middleware
As it occurs, this middleware works(I have it working) only for internal requests(routing requests inside application).
Is there any possibility to do it for all requests?
Thanks in advance
.NET Core allows to create custom middlewares to get into MV pipeline. Here is an example:
public class MyMiddleware
{
private readonly RequestDelegate _next;
public MyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
//do your checkings
await _next(context);
}
}
In Startup.cs in Config method just regiester it:
app.UseMiddleware<MyMiddleware>(Options.Create(options));
Since you are talking about doing a call on Outgoing requests, you have two mechanisms to solve the problem:
Use an Aspect Oriented Programming Library (like https://www.postsharp.net)
Implement your own Request class (that has the global behavior you desire) and make sure that all requests are done using this class (or a class that inherits from it).
For the second point, a good mechanism is that the base class provides a SendRequest method that receives an HttpRequestMessage and executes the global code. Classes that inherit from it use this method to send the requests and have no access to the underlying HttpClient (so that they cannot run around the SendRequest method).

Log to database when authorization fail on Web API [Net.Core]

I have a .Net Core Web API with Custom Policy-Based Authorization (policies that check for claims and claims values on a JWT).
I need to log (to a database) every time a user call a Web API function, even when the authorization fail (especially on failures).
To do that I override these methods OnActionExecuting and OnResultExecuted (because i want to log every request on one filter, and, in other filter, the result of the request). But, if the Authorization fail, both filters never were trigged.
That's because the Authorization filter goes before the other filters (and if the request is unauthorized, short-circuit the pipeline).
So, when a user call a method without authorization I can't log it (i'm using Serilog to write a log file on the server, and works fine when authorization fail, but I want to log it to the database like when authorization is fine).
I try to write some filter before or after Authorization but I couldn't do it. May be i'm not thinking in the right way, and is more simple.
I read all this, but i couldn't figured out yet:
ASP .Net Core Filters
ASP .NET Core Custom Policy-Based Authorization
Asp.Net Core policy based authorization ends with 401 Unauthorized
How do you create a custom AuthorizeAttribute in ASP.NET Core?
Custom authorization attribute in .NET Core
Thanks!
Have you tried the following options:
Using a global filter where you override the order, something like:
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc(options =>
{
options.Filters.Add(typeof(MyLoggingFilter), -2);
options.Filters.Add(typeof(MyAuthFilter), -1);
});
}
For attribute based filters you can implement IOrderedFilter
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
internal sealed class MyAuthorizationAttribute : Attribute, IAuthorizationFilter, IOrderedFilter
{
public int Order => -2;
}
Inject a logger to the AuthFilter itself
public MyAuthFilter(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<MyAuthFilter>();
}
Sounds like you want to log higher in the .NET pipeline?
You could take a look at the DelegatingHandler class rather than filters. These handlers are executed much higher in the pipeline, before your auth filters.
public class MyLogMessageHandler : DelegatingHandler
{
protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// Do logging with request or HttpContext.Current
}
}
In your global.asax.cs (or equiv), u would then register the handler:
GlobalConfiguration.Configuration.MessageHandlers.Add(new MyLogMessageHandler());
Take a look at When to use HttpMessageHandler vs ActionFilter?
Also, we have an API logging and analytics solution that may helpful especially if you're on Azure since there is an Azure extension. https://www.moesif.com/features (full disclosure I am the CEO)

Reusing HttpClient for different users

I've been reading a lot about best practices when using HttpClient. Most people recommend reusing it for the lifetime of the application, even though it's IDisposable.
My web application is communicating with various APIs, like Facebook Graph API, Twitter API and Instagram API.
The plan is to create an individual HttpClient for each API it communicates to, which is recommended, because then I can reuse some of the headers.
But now to the question, let's take the Twitter API as an example, each user using my web application has its own authorization header (user bound access token). I believe this means that I can't set the authorization header to the DefaultRequestHeaders of the HttpClient object.
What is the best practice when it comes to reusing HttpClient for multiple users who have different authorization headers?
Could I create a HttpRequestMessage object for each request and set the authorization header on the httpRequestMessage object, instead of setting it to the default one, httpClient.DefaultRequestHeaders.Authorization?
Thanks.
Because there is some cost involved in creating a HttpClient (especially the number of sockets) there are some benefits in reusing a HttpClient instance. It is thread-safe as as well.
In order to have no dependencies between multiple concurrent calls with one client instance the key pattern is to use HttpRequestMessage class and invoke the HttpClient.SendAsync method (instead of using the more convenient HttpClient.GetAsync, PostAsync, ...).
Something like this:
var request = new HttpRequestMessage() {
RequestUri = new Uri("http://api.twitter.com/someapiendpoint"),
Method = HttpMethod.Get
}
// set the authorization header values for this call
request.Headers.Accept.Add(...);
var response = await client.SendAsync(request);
Now the request headers of the HttpRequestMessage will be used (and not the DefaultRequestHeaders anymore).

Can i create OwinMiddleware per request instead creating a global object

I'm working on the webapi project & now we are migrating to Owin/Katana hosting. I have few doubts regarding.
Quest ) Can i create OwinMiddleware per request instead creating a global object?
I'm able to create owinMiddleware but not able to create them per request. I wanted to create them per request so that i can insert a new object in owinMiddleware as dependency. I'm already using unity in webapi so wanted some solution aligned with unity.
I found few links :-
http://alexmg.com/owin-support-for-the-web-api-2-and-mvc-5-integrations-in-autofac/
http://www.tugberkugurlu.com/archive/owin-dependencies--an-ioc-container-adapter-into-owin-pipeline
but not able to adjust a new IoC with old unity. Can anybody suggest any solution
I found a way by which we could achive this :-
app.Use((IOwinContext context, Func<Task> next) =>
{
ILogger logger = {Resolve dependency using Unity};
CustomOwinMiddleware middleware = new CustomOwinMiddleware(context,next, logger);
return middleware.Invoke();
});
By this way I'm able to generate my middle ware per request. Is it the right way to do this ?
I would recommend using a single middleware instance for all requests that can be injected with unity if you so choose. I would then create a lifetimemanager within the invoke method of that middleware and inject whatever functions you want as delegates rather than calling invoke on another middleware. If you need the OwinContext in those functions you can just pass them as parameters.
See this blog post here for more information:
http://codetoast.org/orchard/blog/using-unity-owin-and-web-api-to-organize-log-entries-by-request

Categories