0

私はEFでコードファーストを使用しています。System.NullReferenceException: Object reference not set to an instance of an object というエラーでドロップダウン リストで検証が失敗しているようです。これは、レコードを保存し、検証をテストするために意図的にコントロールを空のままにしたときに発生します。ドロップダウン リスト自体に選択肢がある場合でも発生します。

ここに私の見解の一部があります:

<div class="editor">
    @Html.LabelFor(model => model.EmployeeID)
    @Html.DropDownListFor(model => model.EmployeeID, new SelectList(Model.Employees, "Value", "Text"))
    @Html.ValidationMessageFor(model => model.EmployeeID)
</div>

テキストボックスの検証を使用すると、次のようになります。

<div class="editor">
    @Html.LabelFor(model => model.EmployeeID)
    @Html.TextBoxFor(model => model.EmployeeID, new { style = "width: 250px;" })
    @Html.ValidationMessageFor(model => model.EmployeeID)
</div>

ここに私の作成コントローラーアクションがあります:

    public ActionResult Create()
{
    var e = iEmployeeRepository.GetAll();
    var visitorLogViewModel = new VisitorLogViewModel
    {
        Employees = e.Select(x => new SelectListItem
        {
            Value = x.EmployeeID,
            Text = x.EmployeeName
        })
    };
    return View(visitorLogViewModel);
}

//
// POST: /VisitorLogs/Create

[HttpPost]
public ActionResult Create(VisitorLog visitorlog)
{
    if (ModelState.IsValid) {
        iVisitorlogRepository.Add(visitorlog);
        iVisitorlogRepository.Save();
        return RedirectToAction("Search");
    } else {
        return View();
    }
}

そして私のビューモデル:

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

    [Display(Name = "Visitor Name")]
    public string VisitorName { get; set; }

    [Display(Name = "Company Name")]
    public string CompanyName { get; set; }

    [Required(ErrorMessage = "Employee ID is required.")]
    [Display(Name = "GB Employee")]
    public string EmployeeID { get; set; }

    [Display(Name = "Visit Reason")]
    public string VisitReason { get; set; }

    [Display(Name = "Time In")]
    public DateTime TimeIn { get; set; }

    [Display(Name = "Time Out")]
    public DateTime TimeOut { get; set; }

    [Display(Name = "GB Employee")]
    public string EmployeeName { get; set; }

    public IEnumerable Employees { get; set; }
    public VisitorLog VisitorLog { get; set; }
}

そして、検証のための私の部分モデル:

    [MetadataType(typeof(VisitorLogMetaData))]
public partial class VisitorLog
{

}

public class VisitorLogMetaData
{
    [Required(ErrorMessage = "Visitor name is required.")]
    [MaxLength(128)]
    public string VisitorName { get; set; }

    [Required(ErrorMessage = "Company name is required.")]
    [MaxLength(128)]
    public string CompanyName { get; set; }

    [Required(ErrorMessage = "GB Employee is required.")]
    [MaxLength(128)]
    public string EmployeeID { get; set; }

    [Required(ErrorMessage = "Visit reason is required.")]
    [MaxLength(254)]
    public string VisitReason { get; set; }

    [Required(ErrorMessage = "Time in is required.")]
    public DateTime TimeIn { get; set; }

    [Required(ErrorMessage = "Time out reason is required.")]
    public DateTime TimeOut { get; set; }
}

そして最後に私のモデル:

    public partial class VisitorLog
{
    public int Id { get; set; }
    public string VisitorName { get; set; }
    public DateTime TimeIn { get; set; }
    public DateTime TimeOut { get; set; }
    public string CompanyName { get; set; }
    public string EmployeeID { get; set; }
    public string VisitReason { get; set; }

    // Navigation properties
    [ForeignKey("EmployeeID")]
    public virtual Employee Employee { get; set; }
}

DropDownListFor に関して MVC カミソリにバグがあることを読みましたが、それが私の状況に当てはまるかどうかはわかりません。いくつかの解決策を試しましたが、うまくいきませんでした。私は4.5フレームワークを使用しています。

ありがとう。

編集:

ページを送信すると、ドロップダウン要素でエラーが停止することに気付きました。

@Html.DropDownListFor(model => model.EmployeeID, new SelectList(Model.Employees, "Value", "Text"))

Model.Employees のモデルは null です。ページが送信されたときにバインディングが失われているようです。

4

1 に答える 1

0

わかりました。クラスにいくつかの基本的な変更を加えました。まず、コントローラーのpostメソッドを変更しました。以前はモデルを投稿に渡していましたが、現在はビューモデルを渡し、リポジトリを介して保存する前にモデルにマッピングしています。

    //
    // POST: /VisitorLogs/Create

    [HttpPost]
    public ActionResult Create(VisitorLogViewModel visitorLogViewModel)
    {
        var e = iEmployeeRepository.GetAll();
        VisitorLog visitorLog = new VisitorLog();
        visitorLog.Id = visitorLogViewModel.Id;
        visitorLog.VisitorName = visitorLogViewModel.VisitorName;
        visitorLog.CompanyName = visitorLogViewModel.CompanyName;
        visitorLog.EmployeeID = visitorLogViewModel.EmployeeID;
        visitorLog.TimeIn = visitorLogViewModel.TimeIn;
        visitorLog.TimeOut = visitorLogViewModel.TimeOut;
        visitorLog.VisitReason = visitorLogViewModel.VisitReason;
        visitorLogViewModel.Employees = new SelectList(e, "EmployeeID", "EmployeeName");

        if (ModelState.IsValid)
        {
            iVisitorlogRepository.Add(visitorLog);
            iVisitorlogRepository.Save();
            return RedirectToAction("Search");
        } else {
            return View(visitorLogViewModel);
        }
    }

次に、「必須」属性(検証)をビューモデルに追加する必要がありました。

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

    [Required(ErrorMessage = "Visitor name is required.")]
    [MaxLength(128)]
    [Display(Name = "Visitor Name")]
    public string VisitorName { get; set; }

    [Required(ErrorMessage = "Company name is required.")]
    [MaxLength(128)]
    [Display(Name = "Company Name")]
    public string CompanyName { get; set; }

    [Required(ErrorMessage = "GB Employee is required.")]
    [MaxLength(16)]
    [Display(Name = "GB Employee")]
    public string EmployeeID { get; set; }

    [Required(ErrorMessage = "Visit Reason is required.")]
    [MaxLength(254)]
    [Display(Name = "Visit Reason")]
    public string VisitReason { get; set; }

    [Display(Name = "Time In")]
    public DateTime TimeIn { get; set; }

    [Display(Name = "Time Out")]
    public DateTime TimeOut { get; set; }

    [Display(Name = "GB Employee")]
    public string EmployeeName { get; set; }

    public SelectList Employees { get; set; }
}

それが最も効率的な方法かどうかはわかりませんが、今ではすべてが機能しています。誰かがこの方法で何か問題を見つけたら、私に知らせてください。

于 2012-12-04T18:02:27.557 に答える