Passing logical call context from OWIN pipeline to WebApi controller - c#

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 !

Related

How do I instantiate a service from another controller in a controller in ASP.NET Core 6 MVC EF?

Let's say I have a controller that does a thing. This thing needs to be logged, however, I'd like to log it into a database that's accessible through the API, so it is also a controller with a service, repository, and validation.
I have a LoggerService that should update its database by LoggerService.UpdateAsync(), but it's not instantiated in the controller that needs to be logged. How would I do that?
From your description, my understanding is that you want to use dependency injection to create an instance of the desired API controller.
You can tell the MVC to register all your controllers as services:
builder.Services.AddMvc().AddControllersAsServices();
Then you can simply inject the desired controller in your other controller via the DI mechanism and invoke its action method.
For other solutions, you can refer to this link.
Hope this will help you. Please let me know if my understanding is wrong.

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

Can I find the controller in HttpSys pipeline?

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

ASP.Net Core dependency injection | How to access user or route data upon creation

Scenario
I am working to follow the IoC pattern and use the Microsoft DI Framework, but I'm hitting a wall and can't decide if it's my mindset, my approach, or I'm just doing it wrong.
I have a multi-tenant application that utilizes a Utility class to handle isolation and accessing the data of the tenant based on their unique configuration. The tenant is identified during authentication, but the tenant data has to be accessible and handled based on the request. This Utility class is registered under ConfigureServices in the Startup.cs and the constructor requires two parameters - a TenantDbContext and a Tenant.
public class TenantUtility{
public TenantUtility(TenantDbContext context, Tenant tenant){/*...*/}
}
Problem
Realizing that I'm probably pushing the limits of the DI Framework, I'm trying to build an implementationFactory in the Startup.cs. I've tried two approaches for accessing the tenant Id to build the Tenant object: one is using a User Claim, the second is a Route parameter.
services.AddTransient<TenantUtility>((svc)=> {
var tenantContext = svc.GetService<TenantDbContext>();
var accessor = svc.GetService<IHttpContextAccessor>();
var httpContext = accessor.HttpContext;
//httpContext is NULL...
//How do I get access to the tenant?
Common.Tenant t = new Common.Tenant();
//Set Tenant Identifier in t (once I get it)
return new StudentDataManager(tenantContext, t);
});
In both situations, when I setup the ImplementationFactory inside the Startup.cs, I don't have access to the user and I don't have access to the RouteData (or can't figure out how to get it) -- I even tried using IHttpContextAccessor, but the HttpContext property is null.
Am I approaching the pattern incorrectly? Should I be able to use DI for this level of detail be injected into the Utility before the Utility class is passed into the Controller?
You shouldn't pass in non-DI-managed types into services you want the container to provide for you (in this case, your Tenant parameter). Only request services that the container can provide. If you need a tenant, perhaps another service like an ITenantAccessor could be injected and would be able to get one.
I suspect your implementation could be done in middleware (if not using MVC) or as a filter (if using MVC). In either case, you can use DI from the filter or middleware class to inject your tenant service. In the class's invoke method, you will have access to the current context and request and should be able to do the things you need to. Remember that ConfigureServices runs before the app has started, so there is no context and no request is yet being made.
If you want to see some examples of filters, and especially how to do DI into filters, check out:
https://github.com/ardalis/GettingStartedWithFilters
and
http://ardalis.com/real-world-aspnet-core-mvc-filters
If you want to do it in middleware, then these might help:
https://github.com/ardalis/NotFoundMiddlewareSample
and
http://ardalis.com/using-custom-middleware-to-record-and-fix-404s-in-aspnet-core-apps
It seems to me that what you are injecting in the TenantUtility as a frist parameter is a valid abstraction (though it's probably better to use some interface), but the other one is a value-object. You don't generally inject value objects as they are not abstraction of some operations that you need to perform, but data. So I would pass the Tenant as a parameter to an operation on the TenantUtility class.
Another thing that I can suggest is to use a full-blown DI container like SimpleInjector (there are many others like Ninject, CastlWindsor, etc.). They are much more advanced as far as I know and can easily be integrated. Many of them have .Net Core integration already.

ASP.NET detection of HttpHandler MVC vs. WebForms

I'm trying to understand and learn the architecture and pipeline of ASP.NET. So far I understand the architectural overview:
on how we get from client to the IIS webserver (request)
via ISAPI extension to the ASP.NET runtime
from there on into the HTTP Pipeline
and ASP.NET calling the HttpModules and HttpHandler
in case of using MVC, selecting the MvcHandler
which is returned by the MvcRouteHandler
etc etc
Now what I don't understand (or can't find any resource on the web documentating this part), is how does the asp.net runtime detect which HttpHandler it has to select for it's request? So how does it know based on my Visual Studio solution that it's an MVC application for example? How does it figure it out that it should use the MvcHttpHandlers? Is there an assembly scan with Reflection somewhere in the HTTP pipeline? Because it certainly isn't a configuration telling the runtime to use the MvcHandler, or is it?
So basically at what exact point is the HttpContext.CurrentHandler being set?
Application_Start
When the request arrives to IIS and the endpoint corresponds to an
Asp.Net application, then the first event raised is the
Application_Start in the System.Web.HttpApplication object.
RouteTable.Routes.Add
Into this event of an Mvc app you can set the routing rules that do
match endpoint urls with Controllers and Actions methods
in the application and the relative IRouteHandler object type,
that will be typeof(MvcRouteHandler).
(see Scott Guthrie post)
HttpApplication.MapRequestHandler
Therefore, soon after that, when the routing table has been setted up,
in the subsequents events (or better in the methods that compose the
pipeline orchestrated by the Asp.Net Framework under IIS control
(integrated pipeline)) of the Asp.Net http request management,
when it needs to know how to manage the http request itself
(HttpApplication.MapRequestHandler), it get parsed the url in
the HttpContext object against the rules in the routing table,
and when it get found a matching, it is instatiated the right type of
its handler, MvcRouteHandler in our case, which will return the
IHttpHandler object by the method GetHttpHandler(RequestContext): MvcHandler .
(see Msdn MvcRoutHandler.GetHttpHandler)
MvcHandler.ProcessRequest
MvcHandler in turn, will give start to the real MVC request handling
through the Asp.Net pipeline event ProcessRequest: and so will
be instatiated the right Controller through the
ControllerFactory, and will be called the Execute method of the Controller abstract base class of the instatiated
controller object, and finally the right Action through the
ActionInvoker.
(see Msdn MvcHandler.ProcessRequest, and The Asp.Net Mvc pipeline)
final note on RouteCollection.MapRoute The Visual Studio starter template for MVC projects creates project that use MapRoute extension method
instead of RouteTable.Routes.Add. This method is very useful
because avoids to have to use always typeof(MvcRouteHandler)
expression when adding new url routing to the project.
(see Asp.Net Routing and Asp.Net Mvc)

Categories

Resources