【问题标题】:Saving from a view model to a model in ASP.NET MVC从视图模型保存到 ASP.NET MVC 中的模型
【发布时间】:2013-01-10 09:57:55
【问题描述】:

我有两个模型,一个代码模型和一个标签模型,它们通过多对多关系链接。我正在尝试添加一个代码条目,其中包括使用视图模型可能选择的许多标签(在我的视图中使用标签的复选框)。我收到错误:

传入字典的模型项是'System.Collections.Generic.List'1[StoRed.Models.Code]'类型的,但是这个字典需要'System.Collections.Generic 类型的模型项.IEnumerable`1[StoRed.Models.CodeTagViewModel]'。

感觉我需要以某种方式将我的数据转换为可接受的格式,然后再尝试将其保存到表中,但我是 MVC 新手,我无法在 Internet 上找到有关我的特定问题的任何有用信息。任何帮助将不胜感激。

代码模型

public class Code
{
    [Key]
    public int CodeID { get; set; }

    [Required]
    [StringLength(30)]
    public string Title { get; set; }

    [Required]
    [StringLength(150)]
    public string Description { get; set; }

    public DateTime DateAdded { get; set; }

    public DateTime LastUpdated { get; set; }

    [Required]
    [StringLength(30)]
    public string Project { get; set; }

    [Required]
    [StringLength(30)]
    public string CMS { get; set; }

    public int DotNetVersion { get; set; }

    [Required]
    [StringLength(150)]
    public string Dependencies { get; set; }

    [StringLength(30)]
    public string Author { get; set; }

    public string CodeFile { get; set; }

    [Required]
    [StringLength(100)]
    public string TFSLocation { get; set; }

    ////Creates a relationship in the DB with Tag
    //[ForeignKey("TagID")]
    public virtual ICollection<Tag> Tags { get; set; }

    ////Purely for API
    //[Required]
    public int TagID { get; set; }
}

标签模型

public class Tag
{
    [Key]
    public int TagID { get; set; }

    [Required]
    [StringLength(30)]
    public string TagName { get; set; }

    public virtual ICollection<Code> Code { get; set; }
}

上下文

public class Context : DbContext
{
    public DbSet<Code> Code { get; set; }

    public DbSet<Tag> Tags { get; set; }
}

视图模型

public class CodeTagViewModel
{
    public Tag Tag { get; set; }
    public Tag TagID { get; set; }
    public List<Tag> Tags { get; set; }


    public int CodeID { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public DateTime DateAdded { get; set; }
    public DateTime LastUpdated { get; set; }
    public string Project { get; set; }
    public string CMS { get; set; }
    public int DotNetVersion { get; set; }
    public string Dependencies { get; set; }
    public string Author { get; set; }
    public string CodeFile { get; set; }
    public string TFSLocation { get; set; }
}

代码控制器的相关部分

    [HttpPost]
    public ActionResult Create(CodeTagViewModel codeTagViewModel)
    {
        if (ModelState.IsValid)
        {
            Code code = new Code();
            Tag tag = new Tag();

            var codeTag = new CodeTagViewModel();

            code.Title = codeTagViewModel.Title;
            code.Description = codeTagViewModel.Description;
            code.DateAdded = codeTagViewModel.DateAdded;
            code.LastUpdated = codeTagViewModel.LastUpdated;
            code.Project = codeTagViewModel.Project;
            code.CMS = codeTagViewModel.CMS;
            code.DotNetVersion = codeTagViewModel.DotNetVersion;
            code.Dependencies = codeTagViewModel.Dependencies;
            code.Author = codeTagViewModel.Author;
            code.CodeFile = codeTagViewModel.CodeFile;
            code.TFSLocation = codeTagViewModel.TFSLocation;
            code.Tags = codeTagViewModel.Tags;

            db.Code.Add(code);
            db.SaveChanges();
            return RedirectToAction("Index");  
        }

        return View(codeTagViewModel);
    }

【问题讨论】:

  • 我看到你在代码和标签之间有一个多对多的关系你有没有指定这种关系在你的上下文中是如何映射的?
  • 我已经添加了上下文,我想我没有,但是在 SQL 中检查我的数据库我可以看到它是多对多的

标签: c# asp.net-mvc entity-framework ef-code-first


【解决方案1】:

您最好的选择是创建某种提供者/经理/服务/工厂/处理程序 - 选择一个最适合其在通过系统的数据流中所做的工作的名称 - 负责获取 ViewModel 并将 ViewModel 的属性映射到域模型的实例中,然后将域模型本身或通过将水合域模型传递到存储库层来将域模型持久保存到数据存储中。您可以手动执行此操作,也可以使用 AutoMapper 之类的工具执行此操作。这是一个快速的手动示例:

使用接口和依赖处理程序在您的 Web 项目中创建一个 CommandHandlers 文件夹:

public interface ICodeCommandHandler
{
    int Save(CodeTagViewModel input);
}

public class CodeCommandHandler : ICodeCommandHandler
{
    private IRepository<Code> repository;

    public CodeCommandHandler(IRepository<Code> repository)
    {
        this.repository = repository;
    }

    public int Save(CodeTagViewModel input)
    {
        Code code = new Code();
        Tag tag = new Tag();
        code.Title = input.Title;
        code.Description = input.Description;
        code.DateAdded = input.DateAdded;
        code.LastUpdated = input.LastUpdated;
        code.Project = input.Project;
        code.CMS = input.CMS;
        code.DotNetVersion = input.DotNetVersion;
        code.Dependencies = input.Dependencies;
        code.Author = input.Author;
        code.CodeFile = input.CodeFile;
        code.TFSLocation = input.TFSLocation;
        code.Tags.Add(tag);

        return repository.Save(code);

    }
}

然后在您的控制器中,通过构造函数注入将 ICodeCommandHandler 注入,就像您在 CodeCommandHandler 中对存储库所做的一样:

private readonly ICodeCommandHandler commandHandler;

public CodeController(ICodeCommandHandler commandHandler)
{
    this.commandHandler = commandHandler;
}

[HttpPost]
public ActionResult Create(CodeTagViewModel codeTagViewModel)
{
    if (!ModelState.IsValid)
    {
        return View(codeTagViewModel);
    }

    var id = codeCommandHandler.Save(codeTagViewModel);
    // maybe do something useful with the document id after save
    return RedirectToAction("Index");  
}

为了让Repository 简洁明了,如下所示:

public interface IRepository<T>
{
    int Save(T entity);
}

public class CodeRepository : IRepository<Code>
{
    public int Save(Code entity)
    {
        using (var context = new Context())
        {
            context.Code.Add(entity);
            context.SaveChanges();
        }
    }
}

我没有详细介绍依赖注入方面的事情,因为这不是问题的一部分,但这应该让您知道从哪里开始

【讨论】:

  • 我仍然无法让它工作。我已经安装了 Auto-Mapper,但我无法实现它。不从头开始理解一切真的阻碍了我了解如何解决这个问题以及到底发生了什么的能力。如果您能提供任何额外的帮助(尤其是关于如何使用 automapper),那将非常感谢。
  • 我建议您从手动执行映射开始,直到您完成所有端到端的工作。在其他一切正常后,您始终可以交换 AutoMapper。以下是AutoMapper 的一些链接:github.com/AutoMapper/AutoMapper/wiki/Getting-startedgithub.com/AutoMapper/AutoMapper/wiki
  • 我正在尝试手动操作,但您给出答案的方式对初学者不太友好,我无法理解正在发生的事情。感谢您抽出时间为我写了一个非常详细的答案,对此我表示感谢。第一个代码sn-p去哪里了?
  • 很公平 :) - 将更新答案以进一步分解 - 你对依赖注入方面还满意还是我应该对此进行扩展?
  • 我在使用存储库时遇到了问题,以前没有见过它们,并且智能感知不喜欢 IRepository 的,并且说不是 Save 中的所有代码路径都返回一个值
猜你喜欢
  • 1970-01-01
  • 2010-11-18
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 2014-01-07
  • 2011-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多