I'm new using Automapper i searched a lot for a right answer but it seems i can't get it in my mind correctly so:
i have this block of code
var user = usersDao.FindById(HttpContext.Current.User.Identity.GetUserId());
var userDto = Mapper.Map<ApplicationUser, UserDto>(user);
if (user.Student != null)
{
userDto.Account = Mapper.Map<Student, StudentDto>(user.Student);
}
if (user.Teacher != null)
{
userDto.Account = Mapper.Map<Teacher, TeacherDto>(user.Teacher);
}
userDto.Account.User = null;
so what i'm trying to do is i have this property in my UserDto class
AccountDto Account
both StudentDto and TeacherDto inherited From it
so i want to make automapper to do self auto mapping to it, if it is from StudentDto or TeacherDto to Account
here is the classes
public class StudentDto : AccountDto
{
}
public class TeacherDto: AccountDto
{
}
public class AccountDto
{
public UserDto User { get; set; }
public string UserId { get; set; }
}
public class UserDto
{
public AccountDto Account { get; set; }
}
is there a simple solution?
Related
I have a profile setup like so:
public class DomainToViewModelProfile : Profile
{
public DomainToViewModelProfile()
{
CreateMap<DataPrivacy, DataPrivacyViewModel>();
CreateMap<DeliveryStage, DeliveryStageViewModel>();
CreateMap<FundedState, FundedStateViewModel>();
CreateMap<Gate, GateViewModel>();
CreateMap<Location, LocationViewModel>();
CreateMap<PersonRole, PersonRoleViewModel>();
CreateMap<Person, PersonViewModel>();
CreateMap<ProjectGate, ProjectGateViewModel>();
CreateMap<ProjectStatus, ProjectStatusViewModel>();
CreateMap<RadarProject, RadarProjectViewModel>();
CreateMap<ManualData, ManualDataViewModel>();
}
}
I, now, have a new model to map nut it is just a class with two properties that are the last two mappings above:
public class DesignProjectViewModel
{
public DesignProjectViewModel()
{
}
public DesignProjectViewModel(RadarProjectViewModel radar, ManualDataViewModel manual)
{
RadarProject = radar;
ManualDataProject = manual;
}
public DesignProjectViewModel(DesignProjectViewModel model)
{
RadarProject = model.RadarProject;
ManualDataProject = model.ManualDataProject;
}
public RadarProjectViewModel RadarProject { get; set; }
public ManualDataViewModel ManualDataProject { get; set; }
}
How do I create a map for this class?
I am facing a problem where my entity framework keeps behaving weirdly when I try to instantiate any class. I am trying to use the default usermanager behaviour to store data in my database. Once I start instantiating a new notification before it adds that notification to the list of notifications available in the application user class it persists those changes and process an error from entity framework saying that there is a multiplicity problem, how can I tell entity framework to not persist changes once I instantiate a class cf here is my controller code :
public string AddFriend(string AddedUserId)
{
var AddedUser = UserManager.FindById(AddedUserId);
var AddingUser = UserManager.FindById(User.Identity.GetUserId());
var friendship = new Friend(AddingUser, AddedUser) { IsInvitation = true };
AddingUser.Friends.Add(friendship);
AddedUser.Notifications.Add(new Notification(AddingUser, "Friend Invitation",
"The user " + AddingUser.FirstName + " " + AddingUser.LastName +
" Sent you a friend invitation", friendship));
UserManager.Update(AddedUser);
UserManager.Update(AddingUser);
return "Friend was added successfully";
}
my Notification class :
[Table("Notifications")]
public class Notification
{
[Key]
public int NotificationId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[Required]
public ApplicationUser AssociatedUser { get; set; }
public Friend AssociatedFrienship { get; set; }
public GroupMember AssociatedGroup { get; set; }
public ChannelMember AssociatedChannel { get; set; }
public Message AssociatedMessage { get; set; }
public bool Consulted { get; set; }
public Notification()
{
}
public Notification(ApplicationUser associatedUser, string title, string content, Friend associatedFriend = null, GroupMember associatedGroup = null, ChannelMember associatedChannel = null, Message associatedMessage = null)
{
AssociatedUser = associatedUser;
Title = title;
Content = content;
AssociatedChannel = associatedChannel;
AssociatedGroup = associatedGroup;
AssociatedFrienship = associatedFriend;
AssociatedMessage = associatedMessage;
Consulted = false;
}
}
my ApplicationUser class:
public partial class ApplicationUser : IdentityUser
{
public virtual List<Notification> Notifications { get; set; }
}
my FluentAPI code :
modelBuilder.Entity<Notification>()
.HasRequired(c => c.AssociatedUser)
.WithMany(c => c.Notifications);
Thanks in advance!
You don't have any foreign key to link AssociatedUser. Try adding a property to link Notification to ApplicationUser using foreign key. Like
public class Notification
{
//rest of properties
//change int to whatever type your primary key is in
//ApplicationUser class. I have Guid for example.
public int ApplicationUser AssociatedUserId {get;set;}
}
Then try modifying configuration like this:
modelBuilder.Entity<Notification>()
.HasRequired(c => c.AssociatedUser)
.WithMany(c => c.Notifications)
.HasForeignKey(n=>n.AssociatedUserId);
I developed my data layer with POCO classes and persistence ignorance principles in my mind. My code was like this
POCO class
public class Report
{
public int Id { get; set; }
public string Name { get; set; }
...
}
}
repository interface
public interface IReportRepository
{
IEnumerable<Report> GetAllReports();
Report GetReport(int reportId);
...
}
and interface implementation with Entity framework code first, like
public class EFReportRepository : BaseRepository, IReportRepository
{
public EFReportRepository(string connectionString)
: base(connectionString)
{
}
public IEnumerable<Report> GetAllReports()
{
return DbContext.Reports.Include(r => r.AggregationParameters).Include(r => r.ErrorAttachment).Include(r => r.ExcelAttachment).Include(r => r.XmlAttachment).ToList();
}
public Report GetReport(int reportId)
{
return DbContext.Reports.Include(r => r.AggregationParameters).Include(r => r.ErrorAttachment).
Include(r => r.ExcelAttachment).Include(r => r.XmlAttachment).SingleOrDefault(r => r.Id == reportId);
}
everything work well until authorization(asp.net identity) was added.
using Microsoft.AspNet.Identity.EntityFramework;
namespace DataRepository.Models
{
public class MyUser : IdentityUser
{
}
}
Now every Report has User that created this report
public class Report
{
public int Id { get; set; }
public string Name { get; set; }
...
public MyUser CreatedByUser { get; set; }
public string CreatedByUserId { get; set; }
...
}
}
Now i have tight dependency with entity framework which i wanted to omit, because of inheritance from IdentityUser class.
How can i exclude this dependency ? I will be thankful for any help )
Update
Now the problem is with creating UserManager object.
UserManager required IUserStore as input parameter. This interface has implementation in Microsoft.AspNet.Identity.EntityFramework namespace and is called UserStore, so my code was like this
manager = new UserManager<MyUser>(new UserStore<MyUser>(MyDbContext)).
But now MyUser class is not inherited from IdentityUser , so this code is broken(UserStore requires this type of class)
I used this approach which works fine as is;
namespace DataRepository.Models
{
public class MyUser
{
public int Id { get; }
//define other user properties
}
}
namespace SomeOtherNamespace
{
public class MyIdentityUser : IdentityUser
{
private MyUser _User;
public MyIdentityUser(MyUser user)
{
_User = user;
}
public int Id { get { return _User.Id; } }
//define other IdentityUser properties by using the MyUser object
}
}
I have a class like this:
[Table("member_activation")]
public partial class MemberActivation
{
[Key]
public Int64 member_id { get; set; }
public String token { get; set; }
}
My db:
public class SMADbContext : DbContext
{
public SMADbContext() : base("SMADB")
{
Database.SetInitializer<SMADbContext>(new NullDatabaseInitializer<SMADbContext>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
public DbSet<Member> Members { get; set; }
public DbSet<MemberActivation> MemberActivations { get; set; }
public DbSet<ApiAccount> ApiAccounts { get; set; }
public DbSet<ApiHardware> ApiHardwares { get; set; }
public DbSet<MemberRelation> MemberRelations { get; set; }
}
In my controller:
[Route("tester")]
[AllowAnonymous]
public IHttpActionResult tester()
{
using (var db = new SMADbContext())
{
var memberActivation = new MemberActivation();
memberActivation.member_id = 10155;
memberActivation.token = "hello";
db.MemberActivations.Add(memberActivation);
return Json(new { dbset = db.MemberActivations.ToList(), memberAct = memberActivation });
}
}
db.MemberActivations.Add(memberActivation); does not work. When I return the json, the dbset does not include the newly created memberActivation. I do not have db.SaveChanges() because it will not save until the memberActivation is pushed to the dbset
You cant set member_id, it is the key and ef uses it as identity. It will be ignored. You can configure ef so that member_id is not identity but that's another topic.
db.MembershipActivations.Add( new MemberActivation { token = "hello"}):
db.SaveChanges();
should work fine.
if however , as it would appear , you have an existing member and you are trying to set a relationship with that entity via a join table. Then you should retrieve that entity and set the memberactivation. Ef will sort the rest out for you. Bit of guessing here as i would need to see the involved entities.
I'm trying to use AutoMapper to take data from a class that has prefixes before property names and map it to a second class that doesn't have those prefixes. However, I don't necessarily want it to always strip out that prefix: I just want it to do it for this particular mapping.
My source class looks like this:
public class AdvancedSearchFilterDataModel
{
// ....
public string ServiceMeterNumber { get; set; }
// ....
}
My destination class looks like this:
[DataContract]
public class ServicesAdvancedSearchFilterData : AdvancedSearchFilterData
{
// ....
[DataMember]
public string MeterNumber { get; set; }
// ....
}
When I try to map values like this, it works:
Mapper.Configuration.RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>();
ServicesAdvancedSearchFilterData servciesFilterData =
Mapper.Map<ServicesAdvancedSearchFilterData>(model);
But I only want "Service" to be recognized as a prefix for certain mappings, since it's also used as a normal part of property names in other mappings. I tried to handle this with a profile, but this didn't work -- no data was mapped:
Mapper.CreateProfile("ServicePrefix").RecognizePrefixes("Service");
Mapper.CreateMap<AdvancedSearchFilterDataModel, ServicesAdvancedSearchFilterData>()
.WithProfile("ServicePrefix");
ServicesAdvancedSearchFilterData servciesFilterData =
Mapper.Map<ServicesAdvancedSearchFilterData>(model);
How can I make it recognize the prefix only when I want it to, either using profiles or some other technique? (I also have other prefixes that I'm going to need it to recognize for other mappings in the same way.)
I achieved this functionality by creating following structure:
I have Person model for my view which is flattened from PersonCombined
public class PersonCombined
{
public Person Person { get; set; }
public Address DefaultAddress { get; set; }
public Contact EmailContact { get; set; }
public Contact PhoneContact { get; set; }
public Contact WebsiteContact { get; set; }
}
public class Person : IWebServiceModel
{
public int ID { get; set; }
public string PersonFirstName { get; set; }
public string PersonSurname { get; set; }
public string PersonDescription { get; set; }
public Nullable<bool> PersonIsActive { get; set; }
}
Then I have separate class for this mapping only that looks like this:
public class PersonCustomMapping : ICustomMapping
{
const string separator = " ";
private static IMappingEngine _MappingEngine;
public IMappingEngine MappingEngine
{
get
{
if (_MappingEngine == null)
{
var configuration = new ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);
configuration.RecognizePrefixes("Person");
configuration.RecognizeDestinationPrefixes("Person");
configuration.CreateMap<Person, MCIACRM.Model.Combine.PersonCombined>();
configuration.CreateMap<MCIACRM.Model.Combine.PersonCombined, Person>();
_MappingEngine = new MappingEngine(configuration);
}
return _MappingEngine;
}
}
}
In my generic view I have mappingEngine property like this:
private IMappingEngine mappingEngine
{
get
{
if (_mappingEngine == null)
{
_mappingEngine = AutoMapper.Mapper.Engine;
}
return _mappingEngine;
}
}
Finally in my generic view constructor i have:
public GenericEntityController(IGenericLogic<S> logic, ICustomMapping customMapping)
: base()
{
this._mappingEngine = customMapping.MappingEngine;
this.logic = logic;
}
And that's how I do mapping:
result = items.Project(mappingEngine).To<R>();
or
logic.Update(mappingEngine.Map<S>(wsItem));
Because I use 1 entity per view I can define custom mapping configuration per entity.
Hope this helps