3

あなたが私を助けてくれることを願っています。私はMVCとEntity Frameworkにまったく慣れていないので、頭を悩ませようとしています。MVC4 と EF5 を使用しています。

これが私がやろうとしていることの概要です...

Site と SiteType の 2 つのエンティティがあります。各サイトは複数の SiteType を持つことができるため、多対多の関係があります。Site、SiteType、SiteSiteType の 3 つのテーブルを作成して、典型的な多対多の関係でデータベースをセットアップします。SiteSiteType には、SiteId と SiteType Id の 2 つの列だけが含まれていました。

エンティティモデルを更新したところ、サイト用にこのようなエンティティを作成するのに完全に機能しました...

public partial class Site
{
    public Site()
    {
        this.SiteTypes = new HashSet<SiteType>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    public virtual ICollection<SiteType> SiteTypes { get; set; }
}

そして、これはSiteType用です

public partial class SiteType
{
    public SiteType()
    {
        this.Sites = new HashSet<Site>();
    }    
    public int Id { get; set; }
    public string Name { get; set; }    
    public virtual ICollection<Site> Sites { get; set; }
}

現在、厳密に型指定されたビューを使用していますが、Site を型として使用する代わりに、作成した SiteViewModel というカスタム ViewModel を使用しています...

public class SiteViewModel
{
    public Site Site { get; set; }
    public bool WasPosted { get; set; }
    public IEnumerable<SiteType> AvailableSiteTypes { get; set; }
    public IEnumerable<SiteType> SelectedSiteTypes { get; set; }
}

この理由は、ここで説明されているように、MVC の CheckBoxList 拡張機能を使用したいからです。

新しいサイトを作成して SiteTypes を追加するとすべてが機能するようになりましたが、編集しようとすると既存のレコードに問題が発生し始めました。

これがコントローラーの編集GETメソッドです....

    public ActionResult Edit(int id = 0)
    {
        Site site = _repository.GetSiteByID(id);
        if (site == null)
        {
            return HttpNotFound();
        }

        var model = new SiteViewModel();
        model.AvailableSiteTypes = _repository.GetSiteTypes();
        model.SelectedSiteTypes = site.SiteTypes;
        model.Site = site;

        return View(model);
    }

そして、postメソッドはもともとこのように見えました....

    [HttpPost]
    public ActionResult Edit(SiteViewModel siteViewModel, int[] siteTypes)
    {

        if (ModelState.IsValid)
        {
            _repository.UpdateSite(siteViewModel.Site, siteTypes);
            _repository.Save();
            return RedirectToAction("Index");
        }

        siteViewModel.AvailableSiteTypes = _repository.GetSiteTypes();
        List<SiteType> selectedSiteTypes = _repository.GetSiteTypes(siteTypes).ToList();
        if (selectedSiteTypes.Count > 0)
        {
            siteViewModel.SelectedSiteTypes = selectedSiteTypes;
        }
        return View(siteViewModel);

    }

今私が抱えていた問題は、更新されたデータを含むフォームから siteViewModel.Site が適切に取り込まれていることでしたが、新しいレコードではなく既存のレコードであっても Id 列が「0」に設定されていました。私はすべてを試しましたが、理由がわかりません。私がそれを機能させる唯一の方法は、「id」パラメーターを取り込んで、このように Site オブジェクトに手動で設定することでした...

HttpPost]
    public ActionResult Edit(int id, SiteViewModel siteViewModel, int[] siteTypes)
    {
        siteViewModel.Site.Id = id;
        ......

しかし、他のすべてがうまく結合しているのに比べて、それは本当に面倒に感じます.

これがこれを行う唯一の方法ですか?何か不足していますか?

私の投稿を読んでくれてありがとう。長すぎてすみません、他にどう説明したらいいのかわかりませんでした...

4

3 に答える 3

2

実際のエンティティをビューに送信することは決して良い考えではありません。ビュー モデルは、ビューをユーザーに表示するために必要なデータのみを取得する必要があります。それぞれの情報をビューに渡す必要がある場合はSite、別のビュー モデルまたは DTO を作成し、代わりにそれを渡します。

siteViewModel.Site = new SiteDto()
{
    Id = site.Id,
    Name = site.Name,
    ...
}

エンティティには、データベース内のレコードにマッピングするために使用される隠しプロパティがあり、ビューとの間でエンティティを渡すと、通常、この情報は失われます。正しいアプローチは、必要なすべてのデータをビューに送信し、それ以上は送信しないことです。次に、POSTメソッドでエンティティを再プルし、ビュー モデルから変更を適用します。

あちこちでこれを行っていることに気付いた場合は、 AutoMapperを使用できます。

于 2012-09-17T11:53:13.220 に答える
0

次のようにするには、編集ページ内にSiteIdを追加する必要があります。

@Html.HiddenFor(model => model.Site.Id)

次に、モデルバインディング/ MVCフレームワーク全体が機能し、IDが保持されていることを確認する必要があります。

于 2012-09-17T11:43:57.253 に答える