Can I find the controller in HttpSys pipeline? - c#

We have services using HttpSys to selfhost a http-listener. We use them to host API's using MVC and implementing our controllers with ControllerBase
Our pipeline looks something like this:
app.UseMiddleware<LogRequests>();
app.UseMiddleware<ValidateAuthentication>();
app.UseMiddleware<FloodingProtector>();
app.UseMiddleware<AdjustCors>();
app.UseMiddleware<FilterOutput>();
app.UseCors("AllowAll");
app.UseMvc();
The LogRequests is our own middeware, where we log information about the request.
In that middleware I would like to understand which Controller the MVC middleware used to execute the request. The Controller has information about a counter with metrics.
I need that information in the LogRequests middleware for updating counters.
Is it possible to get information from the MVC middleware about which Controller was used to execute the request?

There is an Items property on HttpContext which can be used to transport information from a controller back to the pipeline.
That was not usable in my case, as HttpContext is not available in the constructor, which is where I needed it.
Other than that, I don't think there is any good way to send information from Controller to pipeline

Related

Difference between Setting Dependency Resolver and Extending Dependency Lifescope

I am reading the Autofac documentation related to its integration with OWIN, and I get confused by the example they put on their website:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
// STANDARD WEB API SETUP:
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Run other optional steps, like registering filters,
// per-controller-type services, etc., then set the dependency resolver
// to be Autofac.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// OWIN WEB API SETUP:
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
Where I am stuck now is on line config.DependencyResolver = new AutofacWebApiDependencyResolver(container); the webapi dependency resolver is set to autofac, and what is the reason that app.UseAutofacWebApi(config); must be called?
The extension method is to "Extends the Autofac lifetime scope added from the OWIN pipeline through to the Web API dependency scope", but the autofac lifetime scope is shared by setting dependency resolver, is this call still necessary?
It would also be very helpful if you can provide me the use cases of UseAutofacWebApi. Thanks!
The short answer is, yes, it's needed.
Usually a way to test this sort of thing is to see if you can get everything you need without it. I mean, if your app works and things are injected right, that's enough, right?
The longer answer involves you needing to understand that Web API is not natively part of OWIN. OWIN is kind of a bolt-on. The way Web API integrates is, very basically, that the Web API pipeline is jammed into the OWIN pipeline as a middleware step. You can do other stuff with OWIN, too, like adding your own middleware and so on. It's a little beyond the scope of the question here to go through all the details of the ASP.NET pipeline, OWIN, how the middleware interacts, etc. A quick Google search for how does web api work with owin brings up a ton of documentation, blog articles, and explanations.
The important aspect there, though, is that there are basically two parts - the OWIN part, with its pipeline, and the Web API part, with its "sub pipeline."
Since the OWIN pipeline starts before the Web API pipeline, in order to make the two work together and have a request lifetime for the whole of the OWIN pipeline, you have to use the Autofac middleware to do that initialization. Then that same scope from the OWIN pipeline needs to make it into Web API. That also means when the Web API request is done, the OWIN pipeline needs to be able to handle the disposal of things rather than letting Web API handle it.
Hence the documentation: "Extends the Autofac lifetime scope added from the OWIN pipeline through to the Web API dependency scope." It's taking the scope created at the start of the OWIN pipeline and making sure it's the same scope that goes into the Web API pipeline.
Some applications not only have Web API but also ASP.NET MVC, all of which is trying to be coordinated through that OWIN pipeline and needing everything to work together. All of the stuff Autofac has in place to get Web API, MVC, and OWIN wired up is there for a reason - to make sure it all plays nicely together.
Generally if something is optional, the docs will explicitly say so. For example in the Autofac Web API documentation it's noted that it's optional to register filter and model binder provider handling. In this case, it's not really optional.

Aspnetcore API route Template based on Host

I have a set of APIs in an ASP.NET Core (.NET6) project that are exposed both internally (private) and through an API gateway. When served privately, API urls are of the form service.internal/api/v1/resource which is achieved with a RouteAttribute on the ApiController:
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public class ResourceController : ControllerBase
{
// actions
}
When accessed via our api gateway, however, the /api/ component of the url is absent, ie. gateway.com/v1/resource. The gateway performs a transformation on the Url which adds in the extra path segment for the internal/proxied request.
This all works "fine" except in a few circumstances. The primary issue I'm having is with link/url generation for requests coming through the gateway. Location headers added by CreatedAt and link headers generated with IUrlHelper include the /api/ segment of the route with the gateways hostname rendering them invalid. I also have some issues with swagger but I believe they should resolve themselves if I can solve this.
Question: Is there a way to make the route template dynamic based on the host name (which would not be a compile time constant, ie. from config)? For example for requests coming from gateway.com, the route template would be v{version:apiVersion}/[controller] and otherwise would be api/v{version:apiVersion}/[controller]?
It doesn't need to be attribute driven if there's a different way. But my understanding is that the ApiControllerAttribute makes attribute routing required and I wouldn't want to lose the other benefits of that.
If I can get this to work, I'd be able to update the gateway and not have it add the /api/ segment to the proxied urls and it should remove any issues with swagger since the proper paths would be detected by the api explorer.
Unfortunately I have no idea where to start looking. I reviewed some of the routing docs but I didn't see anything that would do the job. I admit I'm out of my league here with minimal aspnetcore experience.
If it matters we are using endpoint routing:
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});

How to delete a specific cookie on startup, using .net core 2?

I need to delete a specific cookie when my app starts, before heading to home page.
I had this inside a controller action method, with a redirect to home page, setting up my startup class to use as route template this controller and action method.
However, there must be a way I can set up a method to delete this cookie, and execute it from startup?
In ASP.NET, this would be done in the methods of global.asax (often in Session_Start(...)). Read more here and here.
In ASP.NET Core, the startup.cs class is where all configurations of services are defined, as well as pipeline requests are managed.
You need to make your own custom middleware for this. Middleware is software that's assembled into an app pipeline to handle requests and responses.
There is another SO question on this topic here (with an answer):
ASP .NET Core webapi set cookie in middleware
For more in-depth cookie management look at this article:
https://www.seeleycoder.com/blog/cookie-management-asp-net-core/
More on middleware:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/write?view=aspnetcore-2.2

Configure session in WEB API 2 with OWIN configuration

I have been trying to configure my Web API 2, that uses the Startup class to configure the API (OWIN Self-Hosting), for it to support the use of the Session object.
I am aware that a REST application should be statless, but I need to use the session anyway.
I have tried this solution, but it won't work.
I have also looked at multiple blog posts and articles that suggest using a custom RouteHandler that overrides the GetHttpHandler method to use a controller that implements IRequiresSessionState (as explained here). But my startup class uses HttpRouteCollection, and my method MapHttpRoute does not support the property RouteHandler.
I have tried moving the route configuration from my Startup class to the Application_Start in a Global.asax I have added, but it is not working either (the requests are not reaching the controllers).
Any suggestion would be much appreciated!
Thank you

Passing logical call context from OWIN pipeline to WebApi controller

I'm trying to pass contextual information on the logical call context (using CallContext.LogicalSetData(CallContextKey, value)) as per Stephen Cleary's post http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html; and inspired by the code in https://github.com/neuecc/OwinRequestScopeContext.
The value will be available through out the OWIN pipeline, but it is not available when the call enters the WebApi controller, the value is not set.
I also noticed that when setting a breakpoint in the controller, I can't see the OWIN pipeline in the call stack. Apparently, ASP.NET is making controller calls on a separate call context.
So,
Why (and how) does ASP.NET isolate the call context from OWIN pipeline to the WebApi controller?
How can I pass contextual data from Pipeline to the controller?
It took me several days to find out why the CallContext is clear in the API controller, until I read this article:
http://www.asp.net/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
If two middleware runs in different IIS stage, they will have different CallContext.
If you are hosting OWIN on IIS and want the same request context in all middlewares, well, use the old HttpContext.Current instead.
I'm not really sure what you mean by passing contextual data from Pipeline to the controller but maybe if you already use Microsoft.AspNet.Identity, you could leverage the use of IAppBuilder.CreatePerOwinContext in order to register your object to the pipeline.
I use to do something like that when I want to pass my contextual object through Owin Pipeline to WebApi Controllers:
startup.cs
//Registration of a delegate factory
app.CreatePerOwinContext<Foo>(Factory.CreateFoo);
factory.cs
//Contextual Object
public static Foo CreateFoo(IdentityFactoryOptions<Foo> options, IOwinContext context)
{
//Owin Context is available here
}
controller.cs
public FooController()
{
var fooObj= HttpContext.Current.GetOwinContext().Get<Foo>();
}
Hope it helps !

Categories

Resources