How to use Automapper in ASP.NET Core to create mapping configuration for the following type of hierarchy - asp.net-core

I would like to map the following hierarchy of entities to the TestViewModel class. I have TestViewModel class with the same member names and perhaps I will add more members to the view model. I am using AutoMapper.
public class TestProfile : Profile
{
public TestProfile ()
{
CreateMap ??????
}
}
public class Test
{
public List<Test1> Tests1 { get; set; }
public int TestId { get; set; }
}
public class Test1
{
public int Test1Id { get; set; }
public string Name { get; set; }
public List<Document> Documents { get; set; }
}
public class Document
{
public int DocumentId { get; set; }
public DateTimeOffset? ChangeDate { get; set; }
public List<Payload> Payloads { get; set; }
}
public class Payload
{
public string PayloadName { get; set; }
}

You didn't tell us what your TestViewModel class looks like, and whether you also have DocumentViewModel, PayloadViewModel, etc. Typically if you are mapping to a another set of classes that have the same naming and structure, like a set of ViewModels, you will want to have a configuration like this:
public class TestProfile : Profile
{
public TestProfile()
{
CreateMap<Test, TestViewModel>();
CreateMap<Test1, Test1ViewModel>();
CreateMap<Document, DocumentViewModel>();
CreateMap<Payload, PayloadViewModel>();
}
}
This will map all like-named properties between the two sets of classes. If your TestViewModel shares the same child entities, then you only need the first line.

Related

How to Map DTO class to "Model" class In generic Repository

I use DTO class in API layer and I struggle to map DTO class to "model" class in generic Repository.cs in core layer.
Repository.cs :
namespace DTOMap.Core.Repository.Generic
{
public class Repository<T> : IRepository<T> where T : class
{
private DTOMapContext _context;
private DbSet<T> _table;
private IMapper _mapper;
public Repository(DTOMapContext context)
{
_context = context;
_table = _context.Set<T>();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<MyMapper>();
});
_mapper = config.CreateMapper();
}
public T Add(T obj)
{
// Here how to use My Mapper to save a book or an author generically
// Sth like :
// temp = _table.Add(_mapper.Map<T>(obj)); Here I want to map Dto to model to save in the db
// return = (_mapper.Map<T>(temp)); Here I want to map Model to DTO to collect it in API
// but I can't have a reference to TDTO
throw new NotImplementedException();
}
}
}
I show you the other classes that I find useful (I only implement Add function for this example and I am a beginner in .Net) :
Author.cs
namespace DTOMap.Core.Models
{
[Table("Author")]
internal class Author
{
[Key]
public int id { get; set; }
[Required, MaxLength(255)]
public string firstName { get; set; }
[Required,MaxLength(255)]
public string lastName { get; set; }
}
}
Book.cs
namespace DTOMap.Core.Models
{
[Table("Book")]
internal class Book
{
[Key]
public int id { get; set; }
[Required,MaxLength(255)]
public string name { get; set; }
[Required]
public int authorId { get; set; }
[Required]
public Author author { get; set; }
}
}
AuthorDTO.cs
namespace DTOMap.Domain.DTO
{
public class AuthorDTO
{
public int id { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
}
}
BookDTO.cs
namespace DTOMap.Domain.DTO
{
public class BookDTO
{
public int id { get; set; }
public string name { get; set; }
public int authorId { get; set; }
public AuthorDTO author { get; set; }
}
}
IRepository.cs
namespace DTOMap.Domain.Interface
{
public interface IRepository<T>
{
T Add(T obj);
}
}
MyMapper.cs
namespace DTOMap.Core
{
public class MyMapper : Profile
{
public MyMapper()
{
CreateMap<Book, BookDTO>();
CreateMap<BookDTO, Book>();
CreateMap<Author, AuthorDTO>();
CreateMap<AuthorDTO, Author>();
}
}
}
program.cs
... Some Fcts
builder.Services.AddTransient<IRepository<BookDTO>, BookRepository>();
builder.Services.AddTransient<IRepository<AuthorDTO>, AuthorRepository>();
... Some Fcts
If you need any other information, please ask me.

HasKey: error while using Fluent API to configure which property should be used as the foreign key

I have two classes (Parent, Child) in ASP.Net Core and I'm using code first approach, my real project is more complex than that, so i have to use this method to migrate to database.
The issue here is when I'm defining the relations in Db Context class i face this error noting that I'm following this Microsoft document https://learn.microsoft.com/en-us/ef/core/modeling/relationships, and you can find the main class below:
Error: Cannot implicitly convert type 'System.Collections.Generic.List<logintest.Models.Chlid>' to 'System.Collections.Generic.IEnumerable<logintest.Models.Child>'. An explicit conversion exists (are you missing a cast?)
public class Parent
{
public int Id { get; set; }
public List<Chlid> Childs { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public Parent Parent { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Childs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Child>()
.HasOne(p => p.Parent)
.WithMany(b => b.Childs)
.HasForeignKey(b => b.ParentId);
}
}

applying an object with a ICollection<Enum> type

In an ASP.NET 3.1 CORE project, using EF, I am trying to implement an object that holds a type of ICollection<Enum> type.
the problem is after reading some tutorials and trying to migrate it to my database something seems off, I will attach screenshots and code for more understanding.
this is the object class :
public class UsersCredentialsModel
{
[Key]
public string UserId { get; set; }
public ICollection<ServiceModel> Services { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Hash { get; set; }
}
The ServiceModel class:
public class ServiceModel
{
[Key]
public string ServiceId { get; set; }
public Service Service { get; set; }
}
The Service Enum Class:
public enum Service : int
{
Badoo = 0,
Tinder = 1,
Grinder = 2,
OkCupid = 3
}
This is the AppDbContext class:
public class AppDbContext : IdentityDbContext<ApplicationUser>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Message>().Property(m => m.Service).HasConversion<int>();
builder.Entity<ApplicationUser>().HasMany<Message>(m => m.Messages).WithOne(u =>
u.User).IsRequired();
builder.Entity<ServiceModel>().Property(m => m.Service).HasConversion<int>();
builder.Entity<UsersCredentialsModel>().HasMany(s => s.Services);
base.OnModelCreating(builder);
}
public DbSet<UsersCredentialsModel> UsersCredentialsModels { get; set; }
public DbSet<ServiceModel> ServiceModel { get; set; }
public DbSet<Message> Messages { get; set; }
public DbSet<CookieModel> CookieModel { get; set; }
public DbSet<ProjectionModel> ProjectionModel { get; set; }
}
This is a picture of the UsersCredentialsModel database schema:
** I believe that there should be a filed called "ServiceId" corresponding to the Id of the second table.
and finally a picture of the ServiceModel schema:
from what I understood you can't implement ICollection of type ENUM and you have to wrap it in a class so basically you need an object to hold the ENUM with an ID and another Id that holds the userId.
The problem is that UserCredentialsModel table should hold an Id property of ServiceId coming from ServiceModel table.
because the class has a field of ICollection but when migrating it does nothing

Automapper maps with wrong property name or I am doing something wrong

I am trying to map my domain entity to DTO. What I am getting in generated query is wrongly concatenated property name.
This is my entity class: (some code is removed for brevity)
public class Product : BaseEntity
{
public int ProductId { get; set; }
public string Name { get; set; }
public virtual EntityUnit EntityUnit { get; set; }
}
This my DTO
public class ProductDto : IMapFrom<Product>
{
public int Id { get; set; }
public string Unit { get; set; }
public void Mapping(Profile profile)
{
profile.CreateMap<Product, ProductDto>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.EntityUnit.Name));
}
}
This is my EntityUnit class:
public class EntityUnit : BaseEntity
{
public int UnitId { get; set; }
public string Name { get; set; }
}
After all this is the generated query:(on mini-profiler)
Actually that must be p.UnitId instead of EntityUnitUnitId (which works). Automapper version is 9.0
What I am doing wrong here?

Pass through multiple dbmodel to a view from a controller

I am using ASP.NET MVC 4.
I have this class:
namespace Attempt4.Models
{
public class UsersModel : DbContext
{
public UsersModel()
: base("name=UsersConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Roles> UserRoles { get; set; }
public DbSet<UsersInRoles> UsersInUserRoles { get; set; }
}
}
and
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
Then there is another class:
public partial class FskWebInterfaceContext : DbContext
{
public FskWebInterfaceContext()
: base("name=FskWebInterfaceContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<trigger_dest_assoc> trigger_dest_assoc { get; set; }
public DbSet<ut_AccessLevel> ut_AccessLevel { get; set; }
public DbSet<ut_Client> ut_Client { get; set; }
public DbSet<ut_ContactID> ut_ContactID { get; set; }
public DbSet<ut_destinations> ut_destinations { get; set; }
public DbSet<ut_DeviceDescription> ut_DeviceDescription { get; set; }
public DbSet<ut_DeviceType> ut_DeviceType { get; set; }
public DbSet<ut_event_log> ut_event_log { get; set; }
public DbSet<ut_GMUTempData> ut_GMUTempData { get; set; }
public DbSet<ut_Triggers> ut_Triggers { get; set; }
public DbSet<ut_User> ut_User { get; set; }
public DbSet<ut_UserAPNdevices> ut_UserAPNdevices { get; set; }
public DbSet<ut_UserClientLink> ut_UserClientLink { get; set; }
}
Now I need to be able to access both of these database contexts from my view.
I know how to pass through just a model for example just UserProfile. But I need to be able to access all of the elements in these two classes.
How can i pass them through from the controller to the View.
And Specifically, once I have passed them through, how do I access them individually in the view?
You have the answer in the comments section of your question:
From what I have been reading I need to make use of a ViewModel class.
So go ahead and define a class that will contain the necessary information. Then in your controller action populate the properties of this model and have it passed to the view.
For example let's suppose that you wanted to access UserProfiles from the first context and the ut_GMUTempData from the second context:
public class MyViewModel
{
public IList<UserProfile> UserProfiles { get; set; }
public IList<ut_GMUTempData> GMUTempData { get; set; }
}
and in your controller action:
public ActionResult Index()
{
using (var ctx1 = new UsersModel())
using (var ctx2 = new FskWebInterfaceContext())
{
var model = new MyViewModel();
model.UserProfiles = ctx1.UserProfiles.ToList();
model.GMUTempData = ctx2.ut_GMUTempData.ToList();
return View(model);
}
}
and now your view becomes strongly typed to the view model and you can access both properties:
#model MyViewModel
... you could use both #Model.UserProfiles and #Model.GMUTempData collections
UPDATE:
As requested in the comments section here's how you could loop through the user profiles in the view:
#model MyViewModel
#foreach (var profile in Model.UserProfiles)
{
<div>#profile.SomePropertyOfTheUserProfileClassThatYouWantToDisplayHere</div>
}