How to keep DbContext and entities internal while injecting into services? - asp.net-core

I am creating an ASP Core MVC application. Within my solution I have Web project (MVC) and a Core project (BLL/DAL).
I thought it would be a good idea to keep my persistence models and DbContext inside Core project as internal, since Web project should never need the persistence models or need to access context directly, it will get all it needs from services.
Core project has an IServiceCollection extension method which allows me to add the DbContext from service layer to the service container in MVC project without MVC needing direct access to it.
The issue comes when I need to use the DbContext inside my service classes in Core project. The service classes must be public for the view layer to access them, but I cannot inject DbContext into them via the constructor because it is internal.
If I want to make the DbContext public so it can be injected, I must also make all of my persistence models public since they are declared with DbSets in the context.
Do I really need to make all of my persistence models public or is there a way to resolve this?

First of all, you need to make Entity public, otherwise, you will not be able to access them in Service Layer. We should reference Entity from Data Access Layer instead of accessing ViewModel from Service Layer in Data Access Layer. And then, you could make DbContext public to be able accessed from Service Layer.
If you want to avoid accessing DbContext directly from Service Layer, you could consider implementing public Repository which will inject DbContext to handle CURD operations.

Related

Get the name of the Background Service Class that is hosting a DI class

Good day all.
I have an asp.net core solution (NopCommerce 4.4) where I'm registering multiple classes that inherit from Microsoft.Extensions.Hosting.BackgroundService. These are using Dependency Injection to get access to several other classes at runtime.
Some of these DI classes need to know which specific class (derived from BackgroundService) they were instantiated in so they can return data specific to the background service that's "hosting" them. For example, each Background Service has it's own ECommerce Store it's responsible for processing data in.
How can I determine what Hosted Service is the "context" for the DI classes that it is requiring?

Initializing UserManager<TUser> in class library project

I have an ASP.NET Core 5.0 MVC application and a .NET 5.0 class library called Application.Data. Due to separation of concerns, I decided that the DbContext and migrations should be contained within the data library. The DDL migrations work perfectly, but I'm having issues seeding AspNetCore.Identity users from within the data library.
Simply put, I want to access a UserManager<MyUser> instance in order to invoke the CreateAsync/AddToRoleAsync methods, but the UserManager constructor takes eight parameters that then also need to be instantiated. My understanding is that I could inject the user manager using the AddIdentity method to the service collection of my MVC project, but since my DbContext is contained within Application.Data, I wouldn't be able to run migration commands from within the MVC project.
What is the best course of action here?

preload and cache data in a Web API OWIN application

I'm building a Web API application using OWIN and hosting in IIS. I now want to preload some data from a database which can be used in the controller methods without loading the data from the database for each request. I have also followed this guide to setup Windsor as IoC container. Does anyone know how to properly set this up?
It's easy to do. In the Startup class, populate one or more classes with the database data. Do this as you would normally load data into a data store.
Register each of these classes with your IoC from the Startup class. It is best to separate the controller from data layer, so create a business logic layer or a repository layer that takes your data store class in the constructor like this:
public class Service
{
private readonly IDataStore _dataStore;
public Service(IDataStore dataStore)
{
_dataStore = dataStore;
}
}
Register the service with your IoC and you should be good to go.
Hope that helps.

MVC4, UnitOfWork + DI, and SimpleAuthentication .. how to decouple?

I'm currently working on an MVC4 project, i make use if Ninject to inject a UnitOfWork into my controllers, and I'm using UnitOfWork + Generic Repository pattern.
I don't like VS2012 MVC4 template because it directly uses database access (db initialization, for example).
My project divides in:
a UI project (the mvc4 application), with Forms Authentication
a Domain project (the db entities, the repositories, the UnitOfWork interface plus two UnifOfWork implementations, one with MOQ and one with EF; they are injected into UI controllers via Ninject).
I looked at this example:
http://kevin-junghans.blogspot.it/2013/03/decoupling-simplemembership-from-your.html
related to this question
SimpleMembership - anyone made it n-tier friendly?
And now I have some question:
How can i inject my UoW here? WebSecurity class is static, there is no contructor, it directly instantiate the UoW to perform activities on db ...
I always have to initialize WebMatrix to directly access DB? This piece of code:
public static void Register()
{
Database.SetInitializer<SecurityContext>(new InitSecurityDb());
SecurityContext context = new SecurityContext();
context.Database.Initialize(true);
if (!WebMatrix.WebData.WebSecurity.Initialized)
WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
}
breaks my decoupling with the Domain .. how can i make WebSecurity using my UnitOfWork for example? what is the best practice?
How can i store additional data (for example, EmailAddress and so on) and retrieve it, without performing a Database query everytime i have to access the User profile? Something like the old CustomPrincipal ... Custom principal in ASP.NET MVC
Thank you!
You have a lot of questions here Marco. Let me take a stab at them.
How to inject a UOW
Static classes and dependency injection do not mix well, as pointed out in this QA. When I first went through this exercise of decoupling SimpleMembership the concentration was just on decoupling from the domain, as discussed in the article you referenced. It was just a first step and it can be improved on, including making it easier for dependency injection. I debated whether to make WebSecurity static or not and went with static because that is how the original SimpleMembership is implemented, making it a more seamless transition for user of the SimpleSecurity. SimpleSecurity is an open source project and contributions are welcome. Making it non-static would not be difficult and probably makes sense in the long run. Once it is made non-static we could use a Factory pattern to create the UnitOfWork and inject the appropriate Factory.
Why do I have to Register WebSecurity?
SimpleSecurity is just a wrapper around the WebMatrix WebSecurity classes, which require initialization. The Register method just makes sure that WebMatrix is initialized and initializes our database. I disagree that having this method call in the Globa.asax couples it with the Domain in any way. Having it work with your UnitOfWork should have nothing to do with the Application Domain, or with having to call a Register method at application start-up.
How can I store additional data (ex: email) and retrieve it, without performing a database query every time?
This is actually accomplished quite easy in .NET 4.5 by using ClaimsPrincipal. All principals in .NET 4.5 inherit from ClaimsPrincipal, which allows you to store information in the principal as claims. Claims are basically key value pairs that let you store any type of data on the user. For example in ASP.NET the roles for a user are stored as claims. To add your own claims you need to do something called claims transformation. Then to retrieve the information you can create a custom claims principal. Adding this to SimpleSecurity would be a nice feature.

How can I send POCO Entities through WCF Service when I don't want to track the entity *later*?

I have an ASP.NET MVC 4 project, where Controller calls a WCF Service layer, that calls Business Layer, that use a Repository of EF 5.0 Entities. Then the results are returned as POCO entities to the Controller.
It works fine while the WCF Service is directly referenced as a Library, but I know it won't work referenced as a Service because they will need to be serialized, and with ProxyCreation enabled this is not possible.
I don't want to create DTOs because I use generated POCO entities, that's why they exist in my humble opinion.
I want to track changes only before the POCO entities reach Service layer.
A lot of people talk about using DTOs even when they are identical to POCOs, if I do that, I could create auto-generated copied classes just with different names to be a "Proxy disabled POCO as DTO", what would be a little strange.
Could I kill the proxy class of a POCO, in a way the object could be serialized when returned from the Service layer?
Also I don't know if this idea is a good practice. But would be great to send "clean" entities to my Controllers, ready to me mapped to ViewModels.
I'm looking for performance too.
The problem is solved using ProxyDataContractResolver. We must use [Serializable] and [DataContract(IsReference=true)] too. With this combination, ProxyCreation can be enabled.
The way we handled this was by doing the following:
Customize the T4 generating the POCO classes so that it generates classes decorated with
[Serializable()] and [DataContract(IsReference=true)] attribute.
Both frontend (views) and backend (wcf service / business layer) references the POCO generated classes, since you won't be using proxy due to IsReference=true.
and that's basically it.
With this, you don't have to create DTO and just use the POCO classes both in backend and frontend.
Keep in mind though, that WCF using IsReference=true handles does not like redundant objects (so this would be an issue on some POCO classes with navigation properties).