在GET
请求中,我可以轻松地创建从后端模型到具有AutoMapper
的自定义DTO的映射。但是,在将AutoMapper
与POST
请求一起使用时,我有些担忧。
假设用户在线订购产品,他向服务器发送包含一些所需数据的POST
请求。事实是,并非后端模型中的每个数据都是由用户发送的。我们假设ID
的{{1}}是Order
,当条目插入数据库时会自动生成GUID
;或者可能还有其他属性自动递增。所有这些无法映射的属性都会导致很多.ForMember(dest => dest.myProperty, opt => opt.Ignore())
个链,以及var mappedInstance = Mapper.Map<PostDTO, BackEndModel>(postDTO)
之后对映射实例的额外处理。
AutoMapper
是不是针对上述情况而设计的?如果后端模型比DTO复杂得多,那么处理模型映射过程的做法是什么?
public class MultipleChoiceQuestion
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid MultipleChoiceQuestionId { get; set; }
[Required]
public string Question { get; set; }
[Required]
public ICollection<PossibleChoice> PossibleChoices { get; set; }
}
public class PossibleChoice
{
[Key, Column(Order = 1), ForeignKey("MultipleChoiceQuestion")]
public Guid MultipleChoiceQuestionId { get; set; }
[Key, Column(Order = 2)]
public int ChoiceIndex { get; set; }
[Required]
public string AnswerText { get; set; }
public MultipleChoiceQuestion MultipleChoiceQuestion { get; set; }
}
用户发送创建新问题的请求。只发送了2个字段。
{
"Question": "How are you?",
"Answers": [
{ "Text": "I am fine." },
{ "Text": "Feeling bad." }
]
}
此阶段缺少的属性:
如果没有手动映射,如何使用AutoMapper
处理这种情况?
答案 0 :(得分:0)
我不确定您在架构中的哪个位置使用AutoMapper,但在执行自动化之前,您可以在概念上将属性列入白名单。例如,如果您在MVC中并且正在进行模型绑定,则有一些技术(例如在UpdateModel方法中)包含或排除属性列表。
答案 1 :(得分:0)
1-定义您的DTO是这样的:
public class MultipleChoiceQuestionDto
{
// This property could stay here, because you may need to use the same DTO for update (PUT),
// which means you need the Id to distinguish and validate the DTO data against the URL id
//public Guid MultipleChoiceQuestionId { get; set; }
public string Question { get; set; }
public ICollection<PossibleChoiceDto> PossibleChoices { get; set; }
}
public class PossibleChoiceDto
{
// This can go from this dto, because this DTO is a child dto for its parent.
//public Guid MultipleChoiceQuestionId { get; set; }
// This property could stay here, because you may need to use the same DTO for update (PUT),
// which means you need the Id to know which Choice was updated.
//public int ChoiceIndex { get; set; }
public string AnswerText { get; set; }
}
2-您可以像这样在实体和相应的Dto之间创建映射,确保从global.asax文件中调用此代码。
Mapper.CreateMap<MultipleChoiceQuestion, MultipleChoiceQuestionDto>();
Mapper.CreateMap<MultipleChoiceQuestionDto, MultipleChoiceQuestion>()
.ForMember(m => m.MultipleChoiceQuestionId, e => e.Ignore()); // you force automapper to ignore this property
Mapper.CreateMap<PossibleChoice, PossibleChoiceDto>();
Mapper.CreateMap<PossibleChoiceDto, PossibleChoice>()
.ForMember(m => m.MultipleChoiceQuestion, e => e.Ignore()) //
.ForMember(m => m.MultipleChoiceQuestionId, e => e.Ignore())
.ForMember(m => m.ChoiceIndex, e => e.Ignore());
3-在你的controller.Post你需要从DTO映射到实体并将映射的实体保存到数据库。
现在,上面的解决方案适用于POST,但是,您需要考虑PUT场景,很快就会意识到您需要将ID包含在DTO中,如果您决定这样做,那么您需要重新访问第2点中的映射,并删除您决定包含在DTO中的属性的忽略代码。
希望有所帮助。