0

私はコードファーストのデータベースを持っています。私の問題を引き起こしているテーブルは

public class Deadline
{
    public Deadline() { }
    public Deadline(Year year)
    {
        this.Year = year;
    }

    public Guid Id { get; set; }

    [Required]
    public Year Year { get; set; }

    [Required]
    [DataType(DataType.Date)]
    [DataAnnotationsExtensions.Date]
    public DateTime From { get; set; }

    [Required]
    [DataType(DataType.Date)]
    [DataAnnotationsExtensions.Date]
    public DateTime To { get; set; }
}

public class Year
{
    public Year(Int32 value) { this.Value = value; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    [Required]
    [Display(Name="Year")]
    [DataAnnotationsExtensions.Year]        
    public Int32 Value { get; set; }

    public virtual Deadline Deadline { get; set; }
}

create get メソッドを持つ年のコントローラーがあります

    public ActionResult Create()
    {
        ViewBag.Id = new SelectList(db.Deadline, "Id", "Id");
        var Year = new Year(db.Year.OrderByDescending(x => x.Value).FirstOrDefault().Value + 1);
        Year.Deadline = new Deadline(Year);
        return View(Year);
    } 

そしてpostメソッド

    [HttpPost]
    public ActionResult Create(Year year)
    {
        if (ModelState.IsValid)
        {
            if (db.Year.Select(x => x.Value).Contains(year.Value))
            {
                ModelState.AddModelError("AlreadyExists", "That year has already been added to the database, please edit instead");
                return View(year);
            }
            db.Year.Add(year);
            db.SaveChanges();
            return RedirectToAction("Index");  
        }

        return View(year);
    }

ただし、新しい年を作成しようとすると(年の値と締め切り日を設定して)、投稿に戻り、モデル状態が無効であり、

年フィールドは必須です。

私がチェックしたところ、投稿メソッドで year.Deadline.Year は実際に null です。知りたいのは、理由 (およびこれを修正する方法) が私を夢中にさせていることです。

@{ Model.Deadline.Year = Model; }

ビューでは何もしませんでした。

編集以下の作品

    using (ProjectSelectionAndAllocation.Models.DatabaseContext Context = new Models.DatabaseContext())
    {
        var h = new Models.Year(1001);
        h.Deadline = new Models.Deadline(h);
        Context.Year.Add(h);
        Context.SaveChanges();
    }
4

3 に答える 3

1

わかりました、問題に関して 2 つの基本的な理論がありますが、とにかく実装する必要がある解決策が 1 つあります。

それでは、解決策から始めましょう。ViewModel を使用します。これは、ビューが表示したいフィールドだけを含む、小さくてフラットな軽量クラスです。データレイヤーと同じであってはなりません。ビューは単にレンダリングする必要があり、ViewModel には表示されるデータのみが含まれている必要があります。

実際のオブジェクトから ViewModel にデータをマップします (これには AutoMapper がよく使われます)。

では、なぜこれが役立つのでしょうか。さて、あなたの問題に関する私の理論は次のとおりです。

1) モデル バインダーは、仮想プロパティを好まない可能性があります。フォームを MVC の関数に返すときは常に、フォーム内のすべての値をフィールドにマップしようとするコードが少しあります。このモデル バインダーは、仮想フィールドを把握できないか、仮想フィールドに自動的にマップしない正当な理由がある可能性があります。いずれにせよ、ViewModel はこれを通常のパブリック プロパティに置き換えます。

2) もう 1 つの可能性ですが、よくわかりませんが、循環参照 (Year -> Deadline -> Year ) があり、モデル バインダーがそれをうまく処理できないことです。繰り返しますが、ViewModel の概念ではそれが取り除かれ、ViewModel に Year フィールドがあるだけです。

于 2012-04-07T22:49:02.710 に答える
0

モデルがビューで適切に配線されていないときに、これが発生しました。このちょっとしたことは、モデルバインダーがポストアクションでモデルを具体化するのを防ぎます。確認すべきことの 1 つは、ビューで適切な asp.net mvc 命名規則を使用していることを確認することです。

于 2012-04-07T22:46:38.873 に答える
0

これが私が念頭に置いていたことです。何が起こっているのかわからない場合に役立つことがよくあります...
詳細が記載された投稿への参照: https://stackoverflow.com/a/10037334/417747
...

バインドが期待どおりに機能しない同様のケースでは、多くの場合、カスタム バインダーを作成することでデバッグに役立ちます。

public class YearClassBinder : DefaultModelBinder
{
    //public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    //{
    //}
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var model = (Year)base.CreateModel(controllerContext, bindingContext, modelType);

        // ...you change, inspect set etc.

        return model;
    }
}

...これは、カスタム バインドの方法であり、「渡す」値を調整します。また、それらに問題があるかどうかなども確認します
(テストする必要があり、いくつかのオプションを試してください。より良い BindModel である可能性があります)。

(そのリンク内に詳細があります)

正確な答えではありませんが、ほとんどの場合、正しい軌道に乗ることができます。

それが役に立てば幸い。

編集: を追加するだけで、この同じアプローチを使用して、必要に応じて Year インスタンスを手動で調整および作成できます。

于 2012-04-07T23:04:01.457 に答える