Configuring Automapper in N-Layer application - c#

I have an N-Layer application as shown below
MyApp.Model - contains edmx and data models
MyApp.DataAccess - Repositories with EF
MyApp.Domain - Domain/business models
MyApp.Services - services(class library)
MyApp.Api - ASP.NET Web API
I am using Unity as my IoC container and Automapper for OO mapping.
My DataAccess layer references Model layer which contains all my Data objects.
I do not want to refer my model project in my Api layer. So returning DomainObjects (business models) from service layer and mapping to DTOs in API layer(DTOs are in API layer).
I configured domainModel to DTO mapping in API layer as below
public static class MapperConfig
{
public static void Configure() {
Mapper.Initialize(
config => {
config.CreateMap<StateModel, StateDto>();
config.CreateMap<StateDto, StateModel>();
//can't do this as I do not have reference for State which is in MyApp.Model
//config.CreateMap<State, StateModel>();
//config.CreateMap<StateModel, State>();
});
}
}
Now my question is how/where to configure my auto mapper mappings to convert my Entity models to Domain models?
To do in my API layer I do not have reference to my model project. I believe I should do this in service layer but not sure how to do that. Please help how to configure this mapping.
Note: Before asking here I googled with all eyes
Where to place AutoMapper map registration in referenced dll says to use static constructor which I do not think a good option to add in all my models (I have 100 models) and another answer says to use PreApplicationStartMethod for which I have to add reference to System.web.dll to my services which is not correct.
https://groups.google.com/forum/#!topic/automapper-users/TNgj9VHGjwg also did not answer my question properly.

You need to create mapping profiles in each of your layer projects, then tell AutoMapper to use those profiles in the topmost/outermost (invoking) layer that references all the lower layers. In your example:
MyApp.Model
public class ModelMappingProfile : AutoMapper.Profile
{
public ModelMappingProfile()
{
CreateMap<StateModel, StateDto>();
CreateMap<StateDto, StateModel>();
}
}
MyApp.Api
public class ApiMappingProfile : AutoMapper.Profile
{
public ApiMappingProfile()
{
CreateMap<State, StateModel>();
CreateMap<StateModel, State>();
}
}
MyApp.Services
Mapper.Initialize(cfg =>
{
cfg.AddProfile<MyApp.Model.ModelMappingProfile>();
cfg.AddProfile<MyApp.Model.ApiMappingProfile>();
});
or if you are using a DI container (e.g. SimpleInjector):
container.RegisterSingleton<IMapper>(() => new Mapper(new MapperConfiguration(cfg =>
{
cfg.AddProfile<MyApp.Model.ModelMappingProfile>();
cfg.AddProfile<MyApp.Model.ApiMappingProfile>();
})));

Related

How do I map the DTO files to my Models in my .Net Core project

I've never worked with a .Net Core project before but have a history with .Net including MVC and entity framework. I'm working with a new .Net Core project which has five solution folders, EHA.PROJ.API, EHA.PROJ.DTO,EHA.PROJ.Repository, EHA.PROJ.Repository.Test and EHA.PROJ.Web. The EHA.PROJ.DTO folder has a number of files such as CategoryDTO.cs which looks like this
namespace EHA.PROJ.DTO
{
public class CategoryDescDTO
{
public int CategoryRef { get; set; }
public string CategoryName { get; set; }
}
}
I'm looking to set up a mapping arrangement to get the data from the EHA.PROJ.DTO files to the model files in my models folder in my EHA.PROJ.Web folder. I've been browsing as I've never done anything like this before as I've previously worked with data from a DAL folder using entity framework and connection done through connection strings. I'm guessing that there must be some process to map the data in my dbContext to connect the files in both folders. I did find some information on AutoMapper but was unsure how to implement it.
This arrangement with .Net Core is new to me so if anyone can help with any examples or point me in the right direction I would be grateful.
Your first problem is having your entities in your web project. Right off the bat, you have tight-coupling between the web project and your data layer, which then pretty much negates the point of all your other layers: DTO, repository, etc. You want to move out your entities and context into a true data layer (i.e. a class library project separate from your web project).
Then, you want to decide how far your data layer should extend. If the API is to feed the Website, then you want to actually remove all dependencies on the data layer from the web project. Your DTO project would be shared between the API and Web projects and your API would send/receive your DTOs, mapping back and forth from your entities under the hood.
However, if you're going to do that, then the repository project should just go away entirely. Just have your API work directly with EF and your entities. Your abstraction is the API itself; there is no need for another. The only reason to have the repository layer is if both the API and Web will both directly utilize the repositories, which isn't a very good pattern actually. You'll inevitably end up with a bunch of duplicated logic specific to each project.
Simply, the repository pattern is superfluous when using an ORM like EF. The ORM is your data layer. You're simply using a DAL provided by a third-party, rather than one you created yourself. The repository pattern only makes sense when working directly with SQL using something like ADO.NET directly. Otherwise, get rid of it.
Having an API is enough of an abstraction, if your goal is simply to hide the data layer. The website knows nothing of the underlying data source, and an API is really just a service layer that returns JSON over HTTP rather than object instances directly, i.e. the API is essentially your "repository" layer.
The situation can be improved even further by moving to a microservices-based architecture. With that, you essentially have multiple small, self-contained APIs that work with just one part of your domain or piece of functionality. Each can utilize EF directly, or an entirely different ORM, or even an entirely different stack. You could have APIs build on Node.js or python, etc. The website simply makes requests to the various services to get the data it needs and doesn't know or care how those services actually work.
I have been using Automapper for quite some time in .NET Core projects due to ease of use and built-in dependency injection.
Install from PM:
Install-Package AutoMapper
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
Register in the Startup.cs, ConfigureServices method:
services.AddAutoMapper(typeof(Startup));
Create a class to keep your mappings, e.g. MappingProfile.cs using Profile from automapper, you can define mappings.
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Operator, OperatorDto>().ReverseMap();
}
}
}
The above mapping tells automapper that Operator can be mapped to OperatorDto and OperatorDto can be mapped to Operator.
In your controller, you can inject an IMapper
private readonly IMapper _mapper;
public OperatorsController(IMapper mapper)
{
_mapper = mapper;
}
and map values like below:
var dto = _mapper.Map<OperatorDto>(op); // Map op object to dto
var op = _mapper.Map<Operator>(dto); // Map dto to op object
Automapper offers custom mappings, should you need it.
While it is very easy to perform mappings with Automapper, you need to learn the framework.
I believe it is worth the effort to learn it as it will save you a lot of time writing mapping code in the future.
This article is a good reference to start: https://buildplease.com/pages/repositories-dto/
My suggestion is to have a DTO assembler that maps your model to the DTO object. So, you start with your DTO class:
namespace EHA.PROJ.DTO
{
public class CategoryDescDTO
{
public int CategoryRef { get; set; }
public string CategoryName { get; set; }
}
}
Then build the assembler:
public class CategoryDescAssembler {
public CategoryDescDTO WriteDto(CategoryDesc categoryDesc) {
var categoryDescDto = new CategoryDescDTO();
categoryDescDto.CategoryRef = categoryDesc.CategoryRef;
categoryDescDto.CategoryName = categoryDesc.CategoryName;
return categoryDescDto;
}
}
Now you implement the service to do all the work required to get the DTO object:
public class CategoryDescService : ICategoryDescService {
private readonly IRepository<CategoryDesc> _categoryDescRepository;
private readonly CategoryDescAssembler _categoryDescAssembler;
public CategoryDescService(IRepository<CategoryDesc> categoryDescRepository, CategoryDescAssembler categoryDescAssembler) {
_categoryDescRepository= categoryDescRepository;
_categoryDescAssembler= categoryDescAssembler;
}
public CategoryDescDTO GetCategoryDesc(int categoryRef) {
var categDesc = _categoryDescRepository.Get(x => x.CategoryRef == categoryRef);
return _categoryDescAssembler.WriteDto(categDesc);
}
}
With the interface looking like this:
public interface ICategoryDescService
{
CategoryDescDTO GetCategoryDesc(int categoryRef);
}
You would then need to add the service to your Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddTransient<ICategoryDescService, CategoryDescService>();
}
Now you can call your service from you view controller.

Automapper - some static class inside project?

I am writing some Web API application, where I have 4 basic layers - API, BusinessLogic(which I call BusinessServices), DAL (which using EF to speak with the database), and EntitiesData(where I have my entities).
API calls businessService, bs ask DAL, DAL using EF is asking database about my EntitiesData.
Ok, now what's the problem ;)
On the BusinessServices, I want to map entities to some DTO, which I can return to API.
I wanted to use AutoMapper, but on tutorials, there are really simple examples, which I understand.
The first question: Should I use 2 IoC containers? Or maybe move my IOC from API to the business services layer?
1st Container is on API level and it contains BusinessServices (like UsesrsService, MessageService, etc.)
The second container would be at BusinessServices level - I want to use it to store my AutoMapper maps.
And this is the second question - what should I do with AutoMapper.
I know, how to create the configuration, did sth like this:
private void Congifure()
{
if(!(configuration == null))
return;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<User, UserDto>();
cfg.CreateMap<Message,MessageDto>();
});
}
but what should I do now? pack it to the IoC container?
From which place in the code I should call my class which is configuring mapper?
In businessServices I have only my business-logic classes and DTO's.
You can pack it into your Startup.cs ConfigureServices method:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<User, UserDto>();
cfg.CreateMap<Message,MessageDto>();
});
var mapper = config.CreateMapper();
services.AddScoped<AutoMapper.IMapper>(c => mapper);
And than inject it into your classes:
public class MyService
{
public MyService(IMapper mapper)
{
...
}
}
I would use one mapper, and put it somewhere vertically to your layer like into "helpers" project. Your mapper has to map between different layers so it should sit "between" them. Just move the logic of creation of MapperConfiguration into separate project and call it from your Startup.cs.
The very first thing in the automapper docs speaks about initialization. This should be done where ever you are bootstrapping your IOC container.
You only need 1 IOC container, making 2 would kind of make them useless as you would have broken the dependency tree into 2 halves.
And you should consider using mapping profiles for your different layers.

Understanding Dependency Injection, IoC in a MVC nTier Application

I understand DI and IoC but I can't seem to understand how to implement it in a nTier application. This is a simple MVC application I'm trying to build with one domain object.
Layers: DAL and UI will reference the BLL Layer.
DAL<--BLL-->UI
DAL will contain EntityFramework, SQLBlogRepository, Blog.cs and Mapper
BAL will contain IBlogRepository, Domain object: Blog.cs
UI will implement Constructor DI of IBlogRepository
This is where I'm stuck. How can I used Ninject so the constructor know to used SqlBlogRepository implementation? I also ran into a few examples that uses "Composition Root" which add more confusion. Then there are example that uses Repository Pattern. The bottom line is, I'm trying implement a nTier MVC application that is loosely couple and used IoC/Dependency Injection. Please help me map out how I can make a call from the UI layer and have the DAL layer return data via BLL layer while all three layer are loosely coupled.
I am assuming you do not have a ninject configuration file created. So here is how we did it where I am at.
To explain what I am doing. You need to have your concrete class implement whatever Interface you want to use.
In the ninject config file you need to bind your Interfaces to your concrete classes. Then you can call ninject to get your interfaces and it will return the concrete class that you want.
If you want to use this in an N- Tier development environment.
DAL <- >BL <->UI
We stuck the ninject configuration in the BL. Since the Bl is the only layer that References the DAL. We exposed the DAL interfaces/concrete classes to the BL via references. Then in the BL we added the Ninject Configuration.
Once that was done in the UI we were able to access all of the Business objects.
ninject starter tutorial
DAL
public interface IRepository
{
//does some things
}
public SQLBlogRepository : IRepository
{
//implements IRepository
}
BL
NINJECT CONFIGURATION FILE
public Foo : IFOO
{
public Foo(IRepository steve){}
}
public interface IFOO
{
}
public class NinjectConfig : NinjectModule
{
public override void Load()
{
Bind<IRepository>.To<SQLBlogRepository>();
Bind<IFOO>.To<Foo>();
}
}
then you use it like so.
var repo = new StandardKernel(new NinjectConfig()).Get<IRepository>();
var fooManager = new StandardKernel(new NinjectConfig()).Get<IFOO>();
The var fooManager, through the power of ninject will autoInstantiate your repo. So you do not need to create it yourself. The config file will handle all the dependancies in the constructor. So you never need to know what constructor creations you need to do. And you can also change the creations in one spot and propagate it out automagically through your code.
In your sample the UI (Mvc Project) is your Composition Root and you can config your dependency in it (with any ioc container like ninject). Your mvc project must have a reference to BLL and DAL layer and you must make a mapping like #gh9 answer in your mvc project.
In your controller you have
public class HomeController : Controller
{
private readonly IFOO _fooBll;
public HomeController(IFOO fooBll){
_fooBll=fooBll;
}
public ActionResult Index()
{
return View();
}
}
and you must have a controller factory to resolve your controller dependency like :
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController) ninjectKernel.Get(controllerType);
}
}

AutoMapper , WCF and multi layers : how to do with dependency

I have a WCF project with multiple layers ( and DTO object ) :
-Service ( WCF Host )
-Business Layer ( or Domain Layer )
-Data Access Layer ( using Entity framework )
To retrieve database informations , i want to use automapper to map Entity object To DTO object .
But if i configure mapping in global.asax , my problem is : the Service layer does not reference Data Access layer (and i dont want this).
How can i do ?
Thanks a lot.
Let's assume you're using AutoMapper 5.1, which includes profile scanning. First, you'd want to put your configuration into profiles at the appropriate places:
public class EntityToDtoProfile : Profile {
public EntityToDtoProfile() {
CreateMap<Entity, Dto>();
}
}
Next, in your WCF app, wherever the app startup is, you'll initialize AutoMapper, passing in the assembly names to scan for profiles:
Mapper.Initialize(cfg => {
cfg.AddProfiles(new [] {
"MyLayeredApp.BLL",
"MyLayeredApp.DAL",
"MyLayeredApp.Service"
});
});
AutoMapper will scan those assemblies for Profiles, and register them in the configuration. Make sure you only call Mapper.Initialize once at startup, like you would any other app-wide configuration.
Or, just create one WCF project, collapse all those projects into one, and use folders for organization instead of all this. That also works.

asp.net mvc how to bind business logic from another project to my asp.net mvc project

I have my business logic layer and data access layer in separated dll , I used active record design pattern to build my bll ... now I need to host my bll and dal in my mvc project ..
I tried to make classes in my models and inherits it's properties and methods from bll (which in another dll) but when I tried to assign base class to inherited one it gives me exception
//Customer class located in mvc model folder which inhireted from EgxCustomer that located in bll in another project
using Egx.EgxBusiness.Inventory;
namespace EgxNMWeb.Models
{
public class Customers:EgxCustomer
{
}
}
//here i try to assign list of EgxCustomer to list of customer
using Egx.EgxBusiness.Inventory;
namespace EgxNMWeb.Models
{
public class CPanelVM
{
Customers currentCustomer { get; set; }
List<Customers> AllNetwork { get; set; }
public CPanelVM()
{
AllNetwork = NMModel.GetCustomerNetwork(currentCustomer.CUST_CODE, Egx.EgxBusiness.Inventory.NM.REF_TYPE.ALL);
}
}
}
what can I do to use my bll which located in another project in my mvc project ?
There is no need for your model classes to be in Models folder. It is just a way to form your code structure (although your view must be in Views folder by default). You can directly use your business logic layer models in your controllers if you want.
I think in your project you can place view models in Models folder.

Categories