如何在没有 Json parseerror (Asp.Net Core MVC) 的情况下从 Model 到 ViewModel 获取数组的某些属性

How to get certain properties of the array from Model to ViewModel without Json parseerror (Asp.Net Core MVC)

我目前正在处理 Asp.Net Core MVC 项目并收到以下消息 class

public class Message
{
    public int Id { get; set; }
    public string SenderId { get; set; }

    [ForeignKey("SenderId")]
    public virtual User Sender { get; set; }

    public string RecipientId { get; set; }
    [ForeignKey("RecipientId")]

    public virtual User Recipient { get; set; }
    public string Content { get; set; }
    public bool IsRead { get; set; }
    public DateTime? DateRead { get; set; }
    public DateTime MessageSent { get; set; }
    public bool SenderDeleted { get; set; }
    public bool RecipientDeleted { get; set; }
}

使用映射器,我得到了以下用于消息审查的 ViewModel:

public class MessageReviewViewModel
{
    public int Id { get; set; }

    public string SenderId { get; set; }
    [ForeignKey("SenderId")]
    public virtual User Sender { get; set; }

    public string RecipientId { get; set; }
    [ForeignKey("RecipientId")]
    public virtual User Recipient { get; set; }

    public string Content { get; set; }
    public bool IsRead { get; set; }
    public DateTime? DateRead { get; set; }
    public DateTime MessageSent { get; set; }
}

现在,我实际上想要获得 Recipient 和 Sender 用户,但是我有这么简单的 MessageReviewViewModel 的原因是因为我得到了这个视图模型的列表,并且有了这个用户 json throws一个错误 & 没有它我有成功的结果。 然而,问题是,为了在收件箱视图中正确显示,我仍然需要收件人和发件人用户的某些属性(他们的主要照片 url、用户名等)。

我的映射器配置如下,以从存储库获取消息:

public async Task<IEnumerable<MessageReviewViewModel>> GetMessagesForUserByUserId(string userId)
    {
        var messages = await messageRepository.GetMessagesForUser(userId);
        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Message, MessageReviewViewModel>();
            cfg.IgnoreUnmapped();
        });
        IMapper mapper = config.CreateMapper();
        var messageList = mapper.Map<IEnumerable<Message>, IEnumerable<MessageReviewViewModel>>(messages);
        return messageList;
    }

在 React 组件中(我已经在 asp.net 核心 mvc 中集成了 react.js)一旦它挂载,我就发出一个获取请求以获取如下消息列表并将 setState messagesList 设置为接收到的数组。

    componentDidMount() {
    const xhr = new XMLHttpRequest();
    xhr.open('get', "/Messages/GetMessages", true);
    xhr.onload = () => {
        const data = JSON.parse(xhr.responseText);
        this.setState({ messagesList: data });
        console.log(this.state.messagesList);
    };
    xhr.send();
}

这是控制器中的动作,被调用:

[HttpGet]
    public async Task<IActionResult> GetMessages()
    {
        var userFromRepo = await  userManager.FindByNameAsync(User.Identity.Name);
        var messages = await messagesService.GetMessagesForUserByUserId(userFromRepo.Id);
        var sortedMessageList = messages.OrderByDescending(m => m.MessageSent);
        return Json(sortedMessageList);
    }

正如我所提到的,除非 MessageReviewViewModel 中没有虚拟用户发件人和虚拟用户收件人,否则一切正常。一旦我将它们写入代码,这就是我得到的错误:

可能值得一提的是,用户 class 对象(例如在我的场景中发件人和收件人)内部也有虚拟属性,我认为这可能是 [=42= 的问题] 解析这些对象,其中有其他对象为属性。 你能告诉我如何将这些属性包含在 ViewModel 中,这样映射器和 JSON 都不会抛出任何错误吗?我什至只获取对象的选定属性(例如,仅字符串用户名、mainphoto url 等)。 也可以,如果有任何 Json 方法,这将解决 ViewModel

中包含的虚拟用户的 parseError

发现mapper也可以配置成用户需要的级别后想通了

消息模型如下

    public class Message
{
    public int Id { get; set; }
    public string SenderId { get; set; }
    [ForeignKey("SenderId")]
    public virtual User Sender { get; set; }

    public string RecipientId { get; set; }
    [ForeignKey("RecipientId")]
    public virtual User Recipient { get; set; }
    public string Content { get; set; }
    public bool IsRead { get; set; }
    public DateTime? DateRead { get; set; }
    public DateTime MessageSent { get; set; }
    public bool SenderDeleted { get; set; }
    public bool RecipientDeleted { get; set; }
}

并且 MessageReviewViewModel 更改为以下内容:

    public class MessageReviewViewModel
{
    public int Id { get; set; }
    public string SenderId { get; set; }
    public string SenderUsername { get; set; }
    public string SenderMainPhotoUrl { get; set; }
    public string RecipientId { get; set; }
    [ForeignKey("RecipientId")]
    public string RecipientUsername { get; set; }
    public string RecipientMainPhotoUrl { get; set; }
    public string Content { get; set; }
    public bool IsRead { get; set; }
    public DateTime? DateRead { get; set; }
    public DateTime MessageSent { get; set; }
}

仅映射器需要如下配置:

public async Task<IEnumerable<MessageReviewViewModel>> GetMessagesForUserByUserId(string userId)
    {
        var messages = await messageRepository.GetMessagesForUser(userId);
        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Message, MessageReviewViewModel>()
            .ForMember(destination=>destination.RecipientUsername,map=>map.MapFrom(
                source=>source.Recipient.UserName)) //gets only string for username instead of whole User model
            .ForMember(destination=> destination.RecipientMainPhotoUrl,map=>map.MapFrom(
                source=>source.Recipient.MainProfilePicture)) //gets only string for profile picture instead of whole User model
            .ForMember(destination=>destination.SenderUsername,map=>map.MapFrom(
                source=>source.Sender.UserName))
            .ForMember(destination=>destination.SenderMainPhotoUrl,map=>map.MapFrom(
                source=>source.Sender.MainProfilePicture)); 
            cfg.IgnoreUnmapped();
        });
        IMapper mapper = config.CreateMapper();
        var messageList = mapper.Map<IEnumerable<Message>, IEnumerable<MessageReviewViewModel>>(messages);
        return messageList;
    }

由于现在所有接收到的数据都是字符串,Json解析没有问题