Use DbContext in other .NET Class Library - asp.net-core

I am using ASP.NET Core with EF Core Code First.
I am defining the dependency injection of the DbContext in service configuration of the Startup.cs of my ASP.NET Core project like described here (https://docs.efproject.net/en/latest/platforms/aspnetcore/new-db.html):
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TestContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DevelopmentDatabase")));
}
But I do not want to use the DbContext in a controller like described at the same site but I want to outsource it to another .NET Core Class Library project together with the Migration.
How do I accomplish this?

Implement the Repository Pattern
It's explained clearly here: Building Your First Web API with ASP.NET Core MVC
But register your repository as:
services.AddScoped<ICustomerRepository, CustomerRepository>();
instead of using .AddSingleton as the link suggests, to avoid this other problem.

I just put my xxxDbContext in a dll library project, but decided to keep migrations in the asp project:
protected override void OnConfiguring(DbContextOptionsBuilder b)
{
base.OnConfiguring(b);
b.UseSqlServer("Data Source=...", x => x.MigrationsAssembly("WebApp1"));
If you don't use MigrationsAssembly, your migrations should go to the dll I believe.
But I'm having problems using the dll in another project, I can't initiate a connection to the database

Related

How to add Dependency of a class library which has no reference in main project in .NET Core Web API

I have two separate .net core library one for Database and other for Service. Following Repository Pattern, my main application (.Netcore web api) has only service reference as I don't want to expose my database to main project. So service has reference of Database and Wep API has reference of Service. For Service I can easily add the reference by using IServiceCollection
services.AddSingleton<IEmployeeServices, EmployeeServices>();
so I can call service from controller with dependency inject
private readonly IEmployeeServices _empServices ;
public EmployeeController(IEmployeeServices empServices)
{
_empServices = empServices;
}
I want to call Database from Service in same manner
private readonly DbContext _context ;
public EmployeeServices(DbContext context)
{
_context = context;
}
but then I need to assign it like following
services.AddSingleton<IDbContext , DbContext >();
so I have to add reference of Database project in my main project but I don't want to expose Database to Main Application.
So, how can I register the dependency of Database project?
You can create a different library just for this. Take a look at examples of Clean Architecture. The configuration of services is done in a dll called .Application and referenced by the WebApi. This way the WebApi does not know about any registered services, it just injects them into his ServiceCollection.
You can create a service collection extension class in your "services project"
You will need this nuget Microsoft.Extensions.DependencyInjection.Abstractions
using Microsoft.Extensions.DependencyInjection;
public static class MyServiceCollectionExtension
{
public static void AddDatabaseProjectServices(this IServiceCollection services)
{
services.AddSingleton<IDbContext,DbContext>();
}
}
And use it in your web-api project :
services.AddDatabaseProjectServices();
Now 2 remarks :
1 ) with this extension your web-api doesn't use database project code directly but still has implicit reference on it because of service project. That's how reference and sub reference work.
The only way to forbid is using internal class (class cannot be used outside of assembly) but you won't be able to inject dependency...
2 ) .net core has a bunch of methods for adding dbcontext so it's better to use them instead of manually AddDbContext

Register class to the DI engine of IServiceCollection

I'm a bit new in this so be easy with me :D
I creaed a web api project based on .net core 6.
i'm trying to find a way to register all the classes i want to the DI engine.
in .net framework 4.7.2 i used castle windsor that way:
_container = new WindsorContainer().Install(FromAssembly.InDirectory(new AssemblyFilter(HttpRuntime.BinDirectory)));
that was called to all the classes in all the project was implemented the IWindsorInstaller wiht the install method and there i was registred the classes of the same project (i had one infrastructure class handled the registration).
i'm searching kind of the same way in .net core to do so.
from the program.cs trigger something that will call all the classes that will handle the registration.
all other projects in my web api main solution are class libreries.
tnx
There is a nuget package called Scrutor that can scan assemblies for classes that implement an interface and then register them into the service collection
https://github.com/khellang/Scrutor
Example:
var collection = new ServiceCollection();
collection.Scan(scan => scan
.FromAssemblyOf<ITransientService>()
.AddClasses(classes => classes.AssignableTo<ITransientService>())
.AsImplementedInterfaces()
.WithTransientLifetime()

How to use Service Fabric service with AspNet Core WebApi and Autofac and run TestServer

I can't figure out how to use an AspNet Core 3.1 Web Api with Service Fabric and Autofac, and also how to have it ready for a TestServer to run for integration/functional testing.
The documentation is very incomplete.
Autofac documentation shows how to modify Program.cs to build autofac container, but it does not mention anything about the Startup.cs class that all the web api have:
https://autofaccn.readthedocs.io/en/latest/integration/servicefabric.html
Also the only example that Autofac has for service fabric is not a web api: https://github.com/autofac/Examples/tree/master/src/ServiceFabricDemo
There are other questions without valid answers:
Service Fabric AspNet Core 3.1 Autofac WebHostBuilder
Does anybody have any example on how to achieve this?
I can achieve the following (please see my GitHub repository with the sample)
Service fabric with stateless AspNet Core WebApi project (dotnet core 3.1)
Using Microsoft Dependency Injection to register services
Using TestServer to run integration tests on the http endpoint, and able to overwrite dependency injection registrations in a clean way without having to create another Startup class
I want the exact same, but using Autofac as DI container.
UPDATE 1:
I can't add Autofac to a WebHostBuilder and the ConfigureServices(IServiceCollection services) must be void as per AspNet Core 3.1+, so this is where I'm stuck. How to replace MS Dependency Injection in my sample
Event after the bounty there is not an answer to this. Maybe it's not possible as service fabric requires WebHost and not generic host.
In any case, I managed to have it working with older versions. Here's my repository where I show a sample on how to run AspNetCore2.1 with DotNetCore2.1 (LTS) and Autofac under Service Fabric. I use the webhost builder, not the generic one.
https://gitlab.com/sunnyatticsoftware/training/sasw-aspnetcore-testing/-/tree/master/aspnetcore2_1_autofac_servicefabric
Still, it'd be nice to eventually have a valid answer to the question.
I have NO idea if this works for the TestServer. It does however work fine with during ordinary hosting.
The exact thing you are looking for would be this line: services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<ContainerBuilder>>(new AutofacServiceProviderFactory(null)));
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(
serviceContext => new KestrelCommunicationListener(
serviceContext,
(url, listener) =>
{
return WebHost
.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<ContainerBuilder>>(new AutofacServiceProviderFactory(null)));
services.AddSingleton(serviceContext)
})
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl | ServiceFabricIntegrationOptions.UseReverseProxyIntegration)
.UseStartup<TStartupType>()
.Build();
}))
};
}
Hope it helps, it took me quite a while to arrive at this solution.

Repository pattern on ASP.NET Core with Identity

How can i implement a Repository pattern with ASP.NET Core Identity?
I found a solution to implement a Repository pattern with ASP.NET Core, but not if you are also using the Identity framework.
The only thing i read is about using a two separate databases: one for Identity tables and another for bussiness data, but i'd like to know if it is possible to implement a repository pattern for a single database on a ASP.NET Core project with Identity.
you can use Autofac as your Dependency Injection in asp.net core. here's the documentation on how to use Autofac in your Asp.net Identity Project: Doc
First Add Identity in your services in Startup.cs
services.AddIdentity<User,IdentityRole>().AddDefaultTokenProviders();
and so on you can register a module in your Service Layer (or Whatever you name it in the repository pattern) and configure them after you register DbContext and your Services:
var dbContextParameter = new ResolvedParameter((pi, ctx) => pi.ParameterType == typeof(IdentityDbContext),
(pi, ctx) => ctx.Resolve<DatabaseContext>());
builder.RegisterType<UserStore<User, IdentityRole<Guid>, DatabaseContext, Guid>>()
.As<IUserStore<User>>().WithParameter(dbContextParameter).InstancePerLifetimeScope();
builder.RegisterType<UserManager<User>>()
.As<UserManager<User>>().WithParameter(dbContextParameter).InstancePerLifetimeScope();
builder.RegisterType<SignInManager<User>>()
.As<SignInManager<User>>().WithParameter(dbContextParameter).InstancePerLifetimeScope();
builder.RegisterType<RoleStore<IdentityRole>>()
.As<IRoleStore<IdentityRole>>().WithParameter(dbContextParameter).InstancePerLifetimeScope();
the code above is the way to register the UserStore, you can make UserManager, SignInManager and other classes like this
note that you can register your Services as their implemented Interfaces like this:
var Service = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(Service)
.AsImplementedInterfaces();
then you can inject identity services into your Service Constructor like this:
public UserService(Data.IRepositoryX<User> repository, IUnitOfWorkDatabaseContext unit, SignInManager<User> signInManager) : base(repository)
{
}

Using WebApi and structure map dependency injection

Although there are so many question on stack overflow which tends similar to my this question but no one is resolving my problem
I was using an MVC4 internet application wherein i had few MVC controller and for dependency injection i was using Structure map. Although dependency injection works fine with MVC controller but when i added an WebApi controller in the same MVC internet application and using the same parameter in constructor of WebApi controller as what i am using in MVC controller but dependency injection is not working with WebApi controller, although if i don't use dependency injection for WebApi controller(parameterless constructor), then it works fine, but for WebApi dependency injection(parameterized constructor) it is throwing an error No parameter less constructor is found.
Conclusion depedencies are not being injected for WebApi Controller in Internet(MVC application).
Few articles suggested to use DependencyResolver.SetResolver(). i used but did not resolve the issue.
The reason why WebApi controller were not working is as following:
Since MVC Controller uses different DependenyResolver instance that is the part of System.Web.MVC .dll and within the System.Web.MVC namespace
http://msdn.microsoft.com/en-us/library/system.web.mvc.idependencyresolver(v=vs.98).aspx
Where as Api Controllers uses DependencyResolver instance that is part of System.Web.Http.
http://msdn.microsoft.com/en-us/library/system.web.http.dependencies.idependencyresolver(v=vs.108).aspx
MVC and WebAPI controllers have a different way of setting their dependency resolver. This is how I set my dependency resolver for Unity:
public void ConfigureForMvc4()
{
DependencyResolver.SetResolver(
new UnityMvc4.UnityDependencyResolver(Container));
}
public void ConfigureForWebApi()
{
GlobalConfiguration.Configuration.DependencyResolver =
new UnityWebApi.UnityDependencyResolver(Container);
}
You need to add Dependency Injection files for WebApi
Install NuGet StructureMap.WebApi2 and in the App_Start/WebApiConfig.cs file, call StructuremapWebApi.Start();
Refer: https://www.exceptionnotfound.net/setting-up-dependency-injection-in-web-api-with-structuremap/