3

多対多の関係でリンクされているコード モデルとタグ モデルの 2 つのモデルがあります。ビューモデルを使用して(ビュー内のタグのチェックボックスを使用して)多くのタグを選択できるコードエントリを追加しようとしています。エラーが発生しています:

ディクショナリに渡されたモデル アイテムのタイプは 'System.Collections.Generic.List'1[StoRed.Models.Code]' ですが、このディクショナリにはタイプ 'System.Collections.Generic.IEnumerable`1[StoRed] のモデル アイテムが必要です.Models.CodeTagViewModel]'.

データをテーブルに保存する前に、どうにかしてデータを許容できる形式に変換する必要があるように感じますが、私は MVC を初めて使用し、特定の問題に関する有用な情報をインターネットで見つけるのに苦労しています。どんな助けでも大歓迎です。

コードモデル

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);
    }
4

1 に答える 1

3

最善の策は、ある種のプロバイダー/マネージャー/サービス/ファクトリー/ハンドラーを作成することです-システムを介したデータのフロー内で実行しているジョブの観点から最も意味のある名前を選択します-ViewModelを取得する責任がありますそして、ドメインモデルをデータストアに永続化する前に、ViewModelのプロパティをドメインモデルのインスタンスにマッピングします。これは、それ自体で、またはハイドレイテッドドメインモデルをリポジトリレイヤーに渡すことによって行われます。これは、手動で行うことも、AutoMapperなどを使用して行うこともできます。簡単な手動の例を次に示します。

CommandHandlersインターフェイスと依存ハンドラを使用して、Webプロジェクトにフォルダを作成します。

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();
        }
    }
}

それは質問の一部ではなかったので、私は物事の依存性注入の側面について詳しくは説明しませんでしたが、これはあなたにどこから始めるべきかについての考えを与えるはずです

于 2013-01-10T10:32:06.837 に答える