AutoMapper postfix not recognized - c#

I'm using AutoMapper v9, and wish to have a postfix on my DTO property names of Dto.
In my profile I add:
RecognizeDestinationPostfixes("Dto");
I validate my mapping with config.AssertConfigurationIsValid(); and immediately it throws with
Unmapped properties:
AccountConnectionIdDto
CreatedDateDto
ModifiedDateDto
IdentityIdDto
AccountIdDto
This is what my DTO looks like:
public class AccountConnectionDto
{
public int AccountConnectionIdDto { get; set; }
public DateTime CreatedDateDto { get; set; }
public DateTime ModifiedDateDto { get; set; }
public Guid IdentityIdDto { get; set; }
public int AccountIdDto { get; set; }
public AccountDto AccountDto { get; set; }
}
Removing the Dto from my model names, and it all works. I feel like the postifx isn't being recognized or utilized at all, am I doing it the correct way?

Related

Dapper.FluentMap bug for nullable decimal

I was looking to find a simple way to map a class property to a table column and I found Dapper fluent map which I thought was going to be a great alternative to the considerable boilerplate code that one would need to write simply to map a property to a column. But it does not seem to work.
FluentMapper.Initialize(c =>
{
c.AddMap(new MarginSummaryMap());
});
[Serializable]
[Table("PbCash")]
public class MarginSummary : Entity
{
public long RunId { get; set; }
public DateTime? BusinessDate { get; set; }
[Write(false)]
public DateTime ProcessDate { get; set; }
public string Broker { get; set; }
public string BrokerAccountId { get; set; }
public string Account { get; set; }
public string Folio { get; set; }
public decimal? ActualExcessOrDeficit { get; set; }
[Write(false)]
public decimal? ProjectedExcessOrDeficit { get; set; }
public string Comment { get; set; }
}
public class MarginSummaryMap : EntityMap<MarginSummary>
{
public MarginSummaryMap()
{
Map(c => c.ActualExcessOrDeficit).ToColumn("ExcessOrDeficit");
}
}
Then when I am trying to save data I get an exception that the column ActualExcessOrDeficit does not exist in the table. Well it does not and the mapping is supposed to convert to the actual column ExcessOrDeficit.
Looks like this is a bug in Dapper.FluentMap since the problem goes way if I change type from decimal? to decimal.
Did anyone have this working - I would love to know how to fix this.

Automapper returning "default" instance of mapped entity

I'm trying to get automapper working for .NET core, and I seem to be missing something important.
I have my automapper set up as follows:
In Startup.cs in my ConfigureServices method, I have the following line:
services.AddAutoMapper(typeof(Startup), typeof(ApplicationDbContext));
I also have a class called MappingProfile which resembles this:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<CfGroup, GroupModel>()
.IgnoreAllUnmapped();
CreateMap<GroupModel, CfGroup>()
.IgnoreAllUnmapped();
...
}
}
The IgnoreAllUnmapped was suggested by another SO question, and it looks like this:
public static IMappingExpression<TSource, TDest> IgnoreAllUnmapped<TSource, TDest>(
this IMappingExpression<TSource, TDest> expression)
{
expression.ForAllMembers(opt => opt.Ignore());
return expression;
}
My CfGroup looks like this:
[Table("Groups")]
public class CfGroup
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[StringLength(100)]
[Required]
public string Name { get; set; }
[DataType(DataType.ImageUrl)]
[StringLength(250)]
public string ImageUrl { get; set; }
[Required]
public int FounderId { get; set; }
[ForeignKey("FounderId")]
public virtual CfUser Founder { get; set; }
[Required]
public bool IsActive { get; set; }
[Required]
public DateTime CreatedTimestampUtc { get; set; }
[StringLength(3000)]
public string About { get; set; }
public virtual ISet<UserGroupMember> Members { get; set; }
public virtual ISet<UserGroupManager> Managers { get; set; }
}
... and my GroupModel looks like this:
public class GroupModel
{
public int Id { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public string About { get; set; }
}
When calling my web api endpoint, I get a collection of CfGroup entities from the database just fine. I then run a command like so:
var dtos = entities.Select(_mapper.Map<GroupModel>);
...but my dtos are "empty"... IOW, the instance is created, but Id value is set to 0 and all the string values are set to null. That is definitely not what is in the entities variable.
I have also tried to explicitly convert it like so:
var dtos = entities.Select(x => _mapper.Map<GroupModel>(x));
and, postulating that it's an IEnumerable issue, tried making a List out of it:
var dtos = entities.Select(x => _mapper.Map<GroupModel>(x)).ToList();
...but no matter what, the DTO's remain instantiated, but with all properties set to their default values.
What am I doing wrong?
I suspect it may be because you are mapping inside your linq expression. try something like this:
var dtos = _mapper.Map<IEnumerable<GroupModel>>(entities.ToList());
So it turns out that the IgnoreAllUnmapped was not the correct way to go; in fact, the mapping seemed to work fine without it. I took out the extra "exception handling" code and it worked as I wanted it to. I was overthinking it.

how to map from a domain model to a view model from MVC controller with AutoMapper

I am trying to figure out how AutoMapper works in creating a map from the domain model to the view model with a complex collection.
Within my domain model (Search.Domain) ,
I have the following:
namespace Search.Domain.Model
{
public class Result
{
public int SearchTime { get; set; }
public List<ResultDetails> Context { get; set; }
}
public class ResultDetails
{
public string Entity { get; set; }
public string Jurisdiction { get; set; }
public DateTime DateReported { get; set; }
public string Description { get; set; }
public DateTime DateEntered { get; set; }
public string AssociatedLink { get; set; }
public int Relevance { get; set; }
}
}
with the MVC project (Search.WebUI) I have the following:
namespace Search.WebUI.Models
{
public class ResultViewModel
{
public int SearchTime { get; set; }
public List<ResultDetails> Context { get; set; }
}
public class ResultDetails
{
public string Entity { get; set; }
public string Jurisdiction { get; set; }
public DateTime DateReported { get; set; }
public string Description { get; set; }
public DateTime DateEntered { get; set; }
public string AssociatedLink { get; set; }
public int Relevance { get; set; }
}
}
Within the controller (HomeController.cs)
namespace Search.WebUI.Controllers
{
public class HomeController : Controller
{
private ISearchResultManager sr = new ResultManager();
public ActionResult Index()
{
ResultViewModel searchresults;
var results = sr.GetSearchResults(5);
Mapper.CreateMap<Search.Domain.Model.Result, ResultViewModel>();
searchresults = Mapper.Map<Search.Domain.Model.Result, ResultViewModel>(results);
return View("Home", searchresults);
}
}
}
The error message that is being generated when run is:
Missing type map configuration or unsupported mapping.
Mapping types:
ResultDetails -> ResultDetails
Search.Domain.Model.ResultDetails -> Search.WebUI.Models.ResultDetails
Destination path:
ResultViewModel.Context.Context.Context0[0]
Source value:
Search.Domain.Model.ResultDetails
In looking at this it appears that the nested List<ResultDetails> is causing an issue but I don't know what I am supposed to do to handle this type of mapping.
Is it correct to go all the way back into the domain for reference to the type? This seems as if I am pulling the domain into the UI which I would not want to do?
Is there another option for mapping domain models to view models in the UI? Basically I was hoping to have a view model within the UI that I could extend beyond the domain model for UI purposes and not put a reference to the domain model.
I am new to autoMapper so this entire thing may be wrong? I would appreciate any suggestions or guidance.
AutoMapper doesn't look at all potential child mapping when mapping a containing class. You need to explicitly add a mapping for the ResultDetails as well:
Mapper.CreateMap<Search.Domain.Model.Result.ResultDetails,
Search.WebUI.Models.ResultDetails>();

Automapper forsourcemember ignore not working

I am pulling from an entity object and trying to map to a model. Here is my class information:
// entity class was auto-generated
**public partial class CategoryType
{
public CategoryType()
{
this.OutgoingCategories = new HashSet<OutgoingCategory>();
}
public int CategoryTypeID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
public virtual ICollection<OutgoingCategory> OutgoingCategories { get; set; }
}**
public class CategoryTypeModel
{
public int CategoryTypeID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
}
My mapper looks like this:
Mapper.CreateMap<CategoryType, CategoryTypeModel>().ForSourceMember(a => a.OutgoingCategories, o => o.Ignore());
When I go to get the mapped list:
Mapper.Map <List<CategoryType>, List<CategoryTypeModel>>(dbo.CategoryTypes.ToList());
I get the error:
Missing type map configuration or unsupported mapping.
I'm new to using Automapper, so I'm not sure what I'm doing wrong. Any help would be great. Thanks.
Well, I said I was new to Automapper. So.... I guess it would help to call this in my Global.asax:
AutoMapperConfig.Configure();
That solved the problem.

How can I avoid recursive Automapper calls with a self referencing object?

I have a class Employee:
public partial class Employee
{
public Employee()
{
this.Employees1 = new HashSet<Employee>();
}
public int Id { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public Nullable<int> ReportsToId { get; set; }
public virtual ICollection<Employee> Employees1 { get; set; }
public virtual Employee ReportsTo { get; set; }
}
And a view model for this:
public class EmployeeEditModel : MappedViewModel<Employee>
{
public int Id { get; set; }
public string Surname { get; set; }
public string FirstName { get; set; }
public string Email { get; set; }
public int? ReportsTo { get; set; }
}
MappedViewModel<T> declares a method:
public class MappedViewModel<TEntity>: ViewModel
{
public virtual TEntity MapToEntity()
{
return (TEntity)Mapper.Map(this, GetType(), typeof(TEntity));
}
}
When I call MapToEntity in an action method, as such
I get an exception from AutoMapper with the message:
Missing type map configuration or unsupported mapping.
Mapping types: Int32 -> Employee System.Int32 -> Leave.Data.Employee
Destination path: Employee.ReportsTo.ReportsTo
Source value: 5
My mappings are defined as follows:
public static void RegisterMaps()
{
Mapper.CreateMap<Employee, EmployeeCreateModel>();
Mapper.CreateMap<EmployeeCreateModel, Employee>();
}
The double reference Employee.ReportsTo.ReportsTo screams out to me that this exception is somehow caused by some sort of cyclical mapping quirk, but I what can I do about this? At very least I would like omit ReportsTo from the mapping and simply do this manually after calling MapToEntity. How can I even to this, and rather, what should I do for this pattern of AutoMapper problem?
You need to do more than simple Mapper.CreateMap as it won't magically figured out how to convert between EmployeeViewModel.ReportsTo (int?) and Employee.ReportsTo (Employee).
Either create a mapping between int and Employee or use the ForMember method to tell AutoMapper how to convert the ReportsTo property.

Categories