Accessing Headers in .NET Core and Autofac - autofac

In Autofac for 4.6 I was able to grab the headers via HttpRequestMessage with builder.RegisterHttpRequestMessage. In .NET Core I cannot find a similiar function. Is there a way to accomplish this in .NET Core?

All the answers here are correct, but let's help you out a little further. Your question essentially boils down to how can you access headers inside a .net core app.
If you are inside a controller
There is a property available in all Controllers named "HttpContext" which you are able to access headers with.
[HttpGet]
public IActionResult Get()
{
var requestHeaders = HttpContext.Request.Headers;
var responseHeaders = HttpContext.Response.Headers;
return View();
}
If you are inside a service
This is a bit more work but still relatively simple.
In your startup.cs, in your ConfigureServices method you need to add a singleton for IHttpContextAccessor. The method will end up looking pretty close to this :
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddMvc();
}
Now, inside your service, you actually need to inject in the IHttpContextAccessor. Here's a sample service that shows you how you might do it.
public class MyService : IMyService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public MyService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public IHeaderDictionary GetRequestHeaders()
{
return _httpContextAccessor.HttpContext.Request.Headers;
}
}
public interface IMyService
{
IHeaderDictionary GetRequestHeaders();
}
Then you need to add to your services collection your service etc, and then have that injected into your controller.
For a bit more info about accessing the HttpContext in .net core read here : http://dotnetcoretutorials.com/2017/01/05/accessing-httpcontext-asp-net-core/

If you're writing middleware, your Invoke method gets an HttpContext passed in.
If you're in a controller, the HttpContext and Request are both properties right on the controller that get populated for you.
If you're in some other service, you'll need an IHttpContextAccessor registered and you can then resolve that. Here's an example from the MVC repo.
None of that is Autofac-specific. That's just how it works in ASP.NET Core.

Related

Blazor Server App and IDbContextFactory not disposing

I have a blazor server application that needs to indirectly connect to a EF core DB context.
None of the blazor components will directly inject an instance of the dbcontext. I am using mediator which will handle all business operations.
The documentation that I have seen so far recommends using IDbContextFactory. I gave it a try but I am not seeing the DbContext created by the factory being disposed. The services that inject IDbContext are not disposed on page changes nor at any other time.
public class QueryHandler : IQueryHandler<Query, Entity>, IDisposable
{
private readonly DbContext dbContext;
public QueryHandler(IDbContextFactory factory)
{
dbContext = factory.CreateDbContext();
}
public Task Handle(Query query)
{
/// do whatever needs to be done.
}
public void Dispose()
{
dbContext.Dispose(); // <-- Dispose never gets called.
}
}
Am I missing something?
The purpose of using a DbContextFactory is to have a DbContext per method.
Exactly because Blazor doesn't offer useful Scopes to handle this.
public class QueryHandler : IQueryHandler<Query, Entity> //, IDisposable
{
...
public QueryHandler(IDbContextFactory factory)
{
_factory = factory;
}
public Task Handle(Query query)
{
using var dbContext = _factory.CreateDbContext();
/// do whatever needs to be done.
}
//public void Dispose() { }
}
This way the DI container and Factory only manage the configuration of the DbContext. Lifecycle management of the DbContext is manual. The Factory is a simple Transient object, is owns no resources.
Manual management usually is with a using statement or using declaration but Blazor also offers an OwningComponentBase. I don't see it being used much.
In Server the DI container exists for the lifetime of the Hub Session and in WASM the lifetime of the Application. Any service objects created within the container, whether Scoped or Transient, implementing IDisposable, are not Disposed until the DI container itself is destroyed. You don't make clear the scope of QueryHandler, but if it's transient that's bad news. You will keep creating new DBContexts without the old ones being disposed.
The purpose of the DbContextFactory is to create unit of work DbContext instances that are used and then quickly disposed correctly. You need to take this approach because DB access will almost certainly be asynchronous. Use a single context and you will quickly hit the situation where you are awaiting one query to complete while trying to use the same context in another operation.
Henk's answer shows you how to use and consume factory created contexts.

Using Entity Framework Core DbContext Pooling with Simple Injector

Looking at the examples of how to use db context pool I see it was designed to be used with ServiceCollection:
var serviceProvider = new ServiceCollection()
.AddDbContextPool<AdventureWorksContext>(options => { //options })
.BuildServiceProvider();
But what about Simple Injector? is it possible to register DB pooling in the Simple Injector container?
p.s. My app is not ASP.NET MVC, it's just a kinda DAL
EF Core DbContext pooling in ASP.NET Core
When integrating Simple Injector in ASP.NET Core, you keep framework and third-party components inside the .NET Core configuration system. This means that enabling Entity Framework Core context pooling is done exactly as Microsoft documents it:
services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(connectionString));
As Simple Injector does not replace the built-in configuration system, you will have to instruct Simple Injector to automatically load missing registrations (such as your DbContext) from the .NET Core configuration system. This can be done by using the AddSimpleInjector and UseSimpleInjector extension methods, as shown here.
private SimpleInjector.Container container;
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(connectionString));
services.AddSimpleInjector(container, options =>
{
options.AddAspNetCore();
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSimpleInjector(container);
container.Verify();
...
}
Using this setup, the BloggingContext can be injected into any component that is resolved from Simple Injector, while the BloggingContext is pooled by Entity Framework. For intance:
// Application compoment registered in and resolved from Simple Injector
public class CommentIsNoSpamValidator : IValidator<PostComment>
{
private readonly BloggingContext context;
// Is injected with BloggingContext from IServiceCollection
public CommentIsNoSpamValidator(BloggingContext context)
{
this.context = context;
}
public IEnumerable<ValidationResult> Validate(PostComment command)
{
// Complex business logic here.
}
}
EF Core DbContext pooling in a .NET (Core) Console application
When it comes to using Entity Framework Core context pooling in a .NET Core console application, the solution will be very similar, although you will have to set up a little bit more:
public void Main()
{
var container = new Container();
var services = new ServiceCollection();
services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(connectionString));
services.AddSimpleInjector(container);
services
.BuildServiceProvider(validateScopes: true)
.UseSimpleInjector(container);
container.Verify();
// Run application code
using (AsyncScopedLifestyle.BeginScope(container))
{
var service = container.GetInstance<MainService>();
service.DoAwesomeStuff();
}
}
So in the end, the DbContext's lifetime is managed by the MS.DI scope, but that scope is managed by Simple Injector's scope.
EF Core DbContext pooling in a library
In case you are building a library, i.e. a non-startup project, please stop what you're doing. Only the application's startup assembly should have a Composition Root, and only the Composition Root should use a DI Container (such as Simple Injector or MS.DI's ServiceCollection). All other libraries in your application should stay oblivious of the (possible) existence of a Container.
You could use
container.Register(() =>
serviceProvider.GetRequiredService<AdventureWorksContext>());
to have the ServiceProvider resolve the dependency as it's requested.
Adding to #Steven's excellent answer, here's his console application answer, but with the context (implicitly) using UseInternalServiceProvider.
var services = new ServiceCollection();
services.AddEntityFrameworkSqlServer();
services.AddSingleton<Microsoft.Extensions.Logging.ILoggerFactory>(new Microsoft.Extensions.Logging.LoggerFactory());
services.AddSingleton<IInterface>(new MyImplemenation());
services.AddDbContextPool<EFViewAndManyToManyDb>(optionsBuilder => {
optionsBuilder.UseSqlServer("");
});
services.AddSimpleInjector(container);
services
.BuildServiceProvider(validateScopes: true)
.UseSimpleInjector(container);
Here's why you'd want to use UseInternalServiceProvider. TLDR: if your DbContext has a dependencies, e.g. IInterface. You'll also need to add the SimpleInjector.Integration.ServiceCollection Nuget package.

Workflow: Creating Dependency Chain with Service Locator Pattern

I'm trying to get dependencies set up correctly in my Workflow application. It seems the best way to do this is using the Service Locator pattern that is provided by Workflow's WorkflowExtensions.
My workflow uses two repositories: IAssetRepository and ISenderRepository. Both have implementations using Entity Framework: EFAssetRepository, and EFSenderRepository, but I'd like both to use the same DbContext.
I'm having trouble getting both to use the same DbContext. I'm used to using IoC for dependency injection, so I thought I'd have to inject the DbContext into the EF repositories via their constructor, but this seems like it would be mixing the service locator and IoC pattern, and I couldn't find an easy way to achieve it, so I don't think this is the way forward.
I guess I need to chain the service locator calls? So that the constructor of my EF repositories do something like this:
public class EFAssetRepository
{
private MyEntities entities;
public EFAssetRepository()
{
this.entities = ActivityContext.GetExtension<MyEntities>();
}
}
Obviously the above won't work because the reference to ActivityContext is made up.
How can I achieve some form of dependency chain using the service locator pattern provided for WF?
Thanks,
Nick
EDIT
I've posted a workaround for my issue below, but I'm still not happy with it. I want the code activity to be able to call metadata.Require<>(), because it should be ignorant of how extensions are loaded, it should just expect that they are. As it is, my metadata.Require<> call will stop the workflow because the extension appears to not be loaded.
It seems one way to do this is by implementing IWorkflowInstanceExtension on an extension class, to turn it into a sort of composite extension. Using this method, I can solve my problem thus:
public class UnitOfWorkExtension : IWorkflowInstanceExtension, IUnitOfWork
{
private MyEntities entities = new MyEntities();
IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
{
return new object[] { new EFAssetRepository(this.entities), new EFSenderRepository(this.entities) };
}
void IWorkflowInstanceExtension.SetInstance(WorkflowInstanceProxy instance) { }
public void SaveChanges()
{
this.entities.SaveChanges();
}
}
The biggest downside to doing it this way is that you can't call metadata.RequireExtension<IAssetRepository>() or metadata.RequireExtension<ISenderRepository>() in the CacheMetadata method of a CodeActivity, which is common practice. Instead, you must call metadata.RequireExtension<IUnitOfWork>(), but it is still fine to do context.GetExtension<IAssetRepository>() in the Execute() method of the CodeActivity. I imagine this is because the CacheMetadata method is called before any workflow instances are created, and if no workflow instances are created, the extension factory won't have been called, and therefore the additional extensions won't have been loaded into the WorkflowInstanceExtensionManager, so essentially, it won't know about the additional extensions until a workflow instance is created.

Implementing passive attributes with dependencies that should be resolved by a DI container

I'm trying to implement passive attributes in an ASP.NET Web API. The filter I'm implementing has a dependency on a repository, which itself has a dependency on a custom DbContext.
In the post it says that you can resolve the component with a DI container, but also that the code should be invoked from Application_Start.
I'm not sure how to implement this, while taking advantage of the DI container's lifetime management capabilities (so that a new DbContext will be used per request). Would injecting an abstract factory be a good solution for this? or is there something simpler that I'm missing.
You can resolve this issue by sliding a Decoraptor in between the Filter and the Repository.
Not knowing a lot about your code, you should be able to define a Decoraptorepository using an Abstract Factory:
public class Decoraptorepository : IRepository
{
private readonly IFactory<IRepository> factory;
public Decoraptorepository(IFactory<IRepository> factory)
{
this.factory = factory;
}
// Just guessing IRepository's member(s) here...
public void Save(Foo foo)
{
this.factory.Create().Save(foo);
}
// other members...
}
This enables your Filter to stay a Singleton, while the actual Repository is being created in a Transient manner.
If you need to dispose of objects too, please refer to the follow-up article on how to decommission Transient objects from within a Decoraptor.

Unit of Work, Entity Framework DBContext Scope

I've run into a bit of a problem with EF looking for the best practice for this problem:
public void TestEntityFramework_UOWImplementation()
{
using (UnitOfWorkInventory uow = new UnitOfWorkInventory())
{
IMaterialRepository repos = new MaterialRepository(uow);
Material mat = GetMaterial("Mikes Material", 1);
mat.CostPrice = 20;
repos.InsertOrUpdate(mat);
uow.Commit();
}
}
private Material GetMaterial(string sku, int clientId)
{
IMaterialRepository repos = new MaterialRepository(new UnitOfWorkInventory();
return repos.Find(sku, clientId);
}
In the TestEntityFramework_UOWImplementation() method, its fine, i call create a scope for my unit of work.. and create a repository inside it.
But when i want to getMaterials() as below.. I have no access to the unit of work or the repository, unless i actually pass it as a parameter! This is clearly not particularly nice.
How do people get around this problem??
Thanks in advance!
Neil
In your implementation you wont have access to the Unit of Work like that. What I do is use an IoC container and Dependency Injection to handle it. I have a WCF service that uses Unit of Work with a repository pattern against EF5.
You can read more about repository pattern, unit of work, and EF here but basically what I do is in the constructor of my service class I inject the Unit of Work like so:
private readonly IUnitOfWork uow;
public LoanService(IUnitOfWork unitOfWork)
{
uow = unitOfWork;
}
Then I can use uow.WhateverMethod in my repos anywhere in the service. I use Ninject to handle the injection of IUnitOfWork. Hope it helps you.
If anyone was looking for a way around this, I done something a bit different.
I used a Dependency Injection framework (StructureMap) to handle all DI, so everytime i instantiate a repository it will retrieve the DBContext from the Service Locator of StructureMap. I also make the dbcontext scope to be for the duration of the request from the webserver.
The advantage here being that everytime i retrieve or inject a DBContext, it will retrieve the same context for the duration of the request meaning i can use this across multiple methods and class! I pass the interface type as a generic param to the constructor, meaning that i can point the repo as different contexts. Helpful in applications where there are lots of dbcontexts.
Repo Constructor Eg:
public class PurchaseOrderRepository<TDbContext> : GenericRepository<PurchaseOrder>, IPurchaseOrderRepository<TDbContext> where TDbContext : DbContext
{
public PurchaseOrderRepository()
: base((TDbContext)ObjectFactory.GetInstance<TDbContext>())
{
}
}
Usage:
//resolves the request scope InventoryContext...
var pRepos = new PurchaseOrderRepository<IInventoryContext>();
and the structure map dependency looks like:
For<IInventoryContext>().HttpContextScoped().Use<InventoryContext>();