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
Related
I am new to ASP.net core. Having a web API connect to database using EntityFramework core. The controller take request, do some analysis, and send the response as below
public class CentoDataController : ControllerBase
{
private readonly CentoWebDBContext _context;
private HPOSubSimHolder _hpoSubSimHolder;
public CentoDataController(CentoWebDBContext context)
{
_context = context;
_hpoSubSimHolder = new HPOSubSimHolder(hpofile);
}
[HttpGet("{id}")]
public ActionResult<CentoData> GetCentoData(string id)
{
IQueryable<CentoData> r = AnalysisMethod(id, _hpoSubSimHolder);
return r;
}
The code works, but _hpoSubSimHolder will be reloaded once a new request comes in. I guess I shouldn't share controller between requests. But how can I avoid reloading _hpoSubSimHolder ?
I can see that you're using .net core dependency injection
If you want that service to be shared across requests, think of making it a Singleton.
You can choose between AddScoped, AddTransient and AddSingleton when registering dependencies.
In your startup.cs class:
public void ConfigureServices(IServiceCollection services)
{
// some code
services.AddSingleton<HPOSubSimHolder>(new HPOSubSimHolder());
}
Singleton means only a single instance will ever be created. That instance is shared between all components that require it. The same instance is thus used always.
Scoped means an instance is created once per scope. A scope is created on every request to the application, thus any components registered as Scoped will be created once per request.
Transient The services created using transient lifetime will be created each time they are requested. This lifetime works best for lightweight services.
(Source)
Controllers are always instantiated per request. To control lifetime of any resources or dependencies the controller should use, you can use the build in Dependency Injection (DI).
Most examples setup DI in your startup.cs ConfigureServices method.
The DI container allows 3 different lifetime states, in your case I guess you can try to add the HPOSubSimHolder as singleton.
I have no idea what HPOSubSimHolder is and what the implementation details are, hence its hard to tell if that'll work for you.
But it would be the "normal" way of setting this up ;)
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).
I'm using ASP.NET WebApi and NLog.
I want to add per-request information like a correlationId to my log messages. In the best case, the user of NLog shouldn't know anything about this. The Logger itself should be able to get the information from the http request.
With Unity i can use the "PerRequestLifetimeManager" to inject those information, but it isn't recommenden. I should rather use HttpContext.Items, but i'm not happy with System.Web and HttpContext.
Is there a possibility to set the information on the server and get them in my logger every time i want to log something, based on the request scope?
NLog has the NLog.MappedDiagnosticContext that you can use to create session type of logging variables. In ASP.Net and WebAPI, using async contexts, you might need to use NLog.MappedDiagnosticsLogicalContext
You'll also need to update the Targets' layouts to include this information:
<target layout="${longdate}|${level:uppercase=true}|${logger}|[${mdc:item=SomeVariable}]${message}" >
Here's how you'd use it:
try
{
NLog.MappedDiagnosticsLogicalContext.Set("SomeVariable", Guid.NewGuid().ToString());
//do your work
Log.Info("Some message here.");
//do more work
Log.Info("Finished!");
}
finally
{
NLog.MappedDiagnosticsLogicalContext.Remove("SomeVariable");
}
Of note, I'd like to see a better way to do this utilizing the C# using statement, like log4net supported.
I've been trying to understand how ASP.NET 5 pipeline middlewares really work. A middleware, as I know, is just a Func<RequestDelegate, RequestDelegate>, which is a pointer to a method that receives a reference to the next request delegate and returns a new one that wraps the next. We can of course, use a class to represent a middleware, something like:
public class MyMiddleware
{
private readonly _next;
public MyMiddleware(RequestDelegate next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
_next = next;
}
public Task Invoke(HttpContext context)
{
// New request delegate code here which can wrap the next one on the pipeline
}
}
Since the RequestDelegate is a delegate that can hold references to methods which receives one HttpContext and returns a Task the Invoke method is the request delegate to be returned and which has access to the next one on the pipeline.
We have then, when coding a middleware, access to the next component of the pipeline, but there is a doubt I have. In the beginning I thought the ideal was always to work the following way:
Check if the middleware can handle the request
If it can, do whatever must be done with the HttpContext
Call the next middleware on the pipeline
So that when I studied this for the first time I thought each middleware should always call the next one. But doing this led to strange behavior as discussed on this question.
Also looking at the source code of some middlewares I see some of them follow another steps:
Check if the middleware can handle the request
If it can, do whatever must be done with the HttpContext and that's all
If not, and only if not call the next one
Is this the real idea of using middlewares? Which way is the correct approach at this? Each middleware do what must be done with the request and always invoke the next or if a midleware can handle the request it doesn't invoke the next anymore?
I believe a middleware should call the next only if it can't handle the request. The reason I think that is because if not, there would be coupling between the middlewares on the pipeline. So that to process the request the middleware would need to be aware of what the previous one did to avoid messing everything. Is this conclusion right?
Middleware exist to make the request pipeline modular, meaning that you can add/remove/replace parts from it as long as you respect the contract. For example, if your application serves some files without any caching, you can add a middleware at the front of the pipeline without altering the rest. They are building blocks.
A middleware can:
Do nothing and pass the request further (e.g. a middleware that is applicable only to POST requests but the current one is GET)
Do nothing to the request, do something else instead and pass it further (e.g. logging)
Do something to the request and pass the request further (e.g. get an authentication token and convert it to an identity, or remove some sensitive information from the request)
End the pipeline and not pass the request further (e.g. StaticFileMiddleware which just returns the file, or MVC when a route matches)
Probably answering your other question too: there are two types of middleware:
Middleware that are designed to do something and pass the data along further (etc. auth, cookies, validation, logging etc)
Middleware that complete the pipeline (static file, MVC, etc).
Of course, some might do both depending on the context. For example auth can end the pipeline if the credentials are incorrect but continue otherwise.
The author of the middleware must decide if the next middleware (if any) should be invoked. In the case of the middleware in your question which returns a message, it should not invoke the next one.
A new asp.net mvc project using owin, webapi, mvc and DI (SimpleInjector) runs fine if I remove the DI lib from the project. However, once introduced, the app blows up when registering the OWIN components for DI. The OWIN startup configuration is being hit and runs without error, but when it comes time to register the dependencies (listed below) I receive the following error:
An exception of type 'System.InvalidOperationException' occurred in Microsoft.Owin.Host.SystemWeb.dll but was not handled in user code
Additional information: No owin.Environment item was found in the context.
SimpleInjector Registration Code:
container.RegisterPerWebRequest<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>());
container.RegisterPerWebRequest<HttpContextBase>(() => new HttpContextWrapper(HttpContext.Current));
// app fails on call to line below...
container.RegisterPerWebRequest(() => container.GetInstance<HttpContextBase>().GetOwinContext());
container.RegisterPerWebRequest(() => container.GetInstance<IOwinContext>().Authentication);
container.RegisterPerWebRequest<DbContext, ApplicationDbContext>();
Update - Full Stack Trace
at
System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase
context) at
WebApplication1.App_Start.SimpleInjectorInitializer.<>c__DisplayClass6.b__2()
in
b:\temp\WebApplication1\WebApplication1\App_Start\SimpleInjectorInitializer.cs:line
41 at lambda_method(Closure ) at
SimpleInjector.Scope.CreateAndCacheInstance[TService,TImplementation](ScopedRegistration2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2
registration, Scope scope) at
SimpleInjector.Advanced.Internal.LazyScopedRegistration2.GetInstance(Scope
scope) at lambda_method(Closure ) at
SimpleInjector.InstanceProducer.GetInstance()
I think the exception is thrown when you call Verify(). Probably at that line, but only when the delegate is called.
Simple Injector allows making registrations in any order and will therefore not verify the existence and correctness of a registration’s dependencies. This verification is done the very first time an instance is requested, or can be triggered by calling .Verify() at the end of the registration process.
I suspect you're registrering the OwinContext only because you need it for getting the IAuthenticationManager.
The problem you face is that the OwinContext is only available when there is a HttpContext. This context is not available at the time the application is build in the composition root. What you need is a delegate which checks the stage of the application and returns a component that matches this stage. You could that by registering the IAuthenticationManager as:
container.RegisterPerWebRequest<IAuthenticationManager>(() =>
AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication);
The delegate will return the Owin controlled IAuthenticationManager when the code runs at 'normal runtime stage' and there is a HttpContext.
But when making an explicit call the Verify() (which is highly advisable to do!) at the end of registration process there is no HttpContext. Therefore we will create a new OwinContext during verifying the container and return the Authentication component from this newly created OwinContext. But only if the container is indeed verifying!
A full and detailed description can be read here as already mentioned in the comments.
Although the question is different, the answer is the same as my answer here.
The problem is that you are injecting HttpContextWrapper into your application and attempting to use its members during application initialization, but at that point in the application lifecycle, HttpContext is not yet available. HttpContext contains runtime state, and it does not make sense to initialize an application within one specific user's context.
To get around this problem, you should use one or more Abstract Factories to access HttpContext at runtime (when it is available) rather than at application initialization, and inject the factories into your services with DI.
Using Ric .Net's answer might work, too, but it will throw an exception every time the application is initialized.
The answer of 'Ric .Net' has pointed me in right direction, but to allow changes to new SimpleInjector, have to change the code as below (as RegisterPerWebRequest is obselete):
container.Register<IAuthenticationManager>(() => AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication, Lifestyle.Scoped);
Also, have to add below two registrations to the container, to allow 'container.Verify()' to work correctly:
container.Register<ApplicationUserManager>(Lifestyle.Scoped);
container.Register<ApplicationSignInManager>(Lifestyle.Scoped);