表单上的验证不断要求MVC上提供所需的ID

时间:2018-10-17 15:53:20

标签: asp.net-mvc asp.net-mvc-4

我正在尝试验证表格。出于某种原因,当我提交表单时,表单验证会显示“ ID字段为必填”。但是,尽管这样说,但我有一个HiddenFor输入应该处理它...

这是我的视图 UserReportForm.cshtml (为便于阅读而缩短):

@model  BugTracker.ViewModels.UserReportViewModel

@{
    ViewBag.Title = "Issue Form";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Report Bug/Request Change</h1>
@Html.ValidationSummary(false, "Please fix the following errors.")
@using (Html.BeginForm("Save", "Report", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <div class="form-group">
        <label>Are you reporting a bug, or requesting a change to a page?</label>
        @Html.DropDownListFor(m => m.Report.RequestTypeID, new SelectList(Model.RequestType, "ID", "RequestBC"), "Select Issue", new { @class = "form-control" })
        @Html.ValidationMessageFor(m => m.Report.RequestTypeID)
    </div>
    <div class="form-group">
        <label>Name of Issue</label>
        @Html.TextBoxFor(m => m.Report.Name, new { @class = "form-control"})
        @Html.ValidationMessageFor(m => m.Report.Name)
    </div>
    <div class="form-group">
        <label>Detailed Description of Issue</label>
        @Html.TextAreaFor(m => m.Report.Description, new { @class = "form-control", @rows = "10"})
        @Html.ValidationMessageFor(m => m.Report.Description)
    </div>

    @Html.HiddenFor(m => m.Report.ID)
    <button type="submit" class="btn btn-primary">Save</button>
}

这是视图模型 UserReportViewModel.c

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BugTracker.Models;
using System.Web.Mvc;

namespace BugTracker.ViewModels
{
    public class UserReportViewModel
    {
        public Report Report { get; set; }
        public IEnumerable<RequestType> RequestType { get; set; }    
    }
}

Report.cs 模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace BugTracker.Models
{
    public class Report
    {
        //For User
        public int ID { get; set; }
        [Required]
        public String Name { get; set; }
        [Required]
        public String Description { get; set; }    
        public RequestType RequestType { get; set; }
        [Display (Name="Request Type")]
        public byte RequestTypeID { get; set; }    
    }
}

在我添加验证之前,这些表单在数据库中获取ID均没有问题(每次递增1)。为什么这会抱怨ID,我该怎么做才能阻止它说是必需的?

编辑:我认为这与它没有太大关系,但是经过进一步审查,我认为我的控制器可能是导致此问题的原因:

新表格

    public ActionResult UserReportForm()
    {
        var requestType = _context.RequestType.ToList();
        var viewModel = new UserReportViewModel
        {
            RequestType = requestType,
        };
        return View(viewModel);
    }

保存表单

    [HttpPost]
    public ActionResult Save(UserReportViewModel viewModel)
    {
        if (!ModelState.IsValid)
        {
            var viewM = new UserReportViewModel
            {
                RequestType = _context.RequestType.ToList(),
            };

            return View("UserReportForm", viewM);
        }
        if (viewModel.Report.ID == 0)
        {
            _context.Reports.Add(viewModel.Report);
        }
        else
        {
            var reportInDb = _context.Reports.Single(c => c.ID == viewModel.Report.ID);
            reportInDb.Name = viewModel.Report.Name;
            reportInDb.Description = viewModel.Report.Description;
            reportInDb.RequestTypeID = viewModel.Report.RequestTypeID;
        }
        _context.SaveChanges();
        return RedirectToAction("Report", "Report", new { stat = 1 });

    }

3 个答案:

答案 0 :(得分:1)

请更新模型并重建项目

public class Report
    {
        //For User-> here add the [Key]
        [Key]
        public int ID { get; set; }
        [Required]
        public String Name { get; set; }
        [Required]
        public String Description { get; set; }    
        public RequestType RequestType { get; set; }
        [Display (Name="Request Type")]
        public byte RequestTypeID { get; set; }    
    }

答案 1 :(得分:1)

如果ID列是自动生成的主键(即身份列),则应使用KeyAttributeDatabaseGeneratedAttribute对其进行标记,如下例所示:

public class Report
{
    // add 2 attributes below
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    [Required]
    public String Name { get; set; }
    [Required]
    public String Description { get; set; }    
    public RequestType RequestType { get; set; }
    [Display(Name="Request Type")]
    public byte RequestTypeID { get; set; }    
}

使用这些属性,无需在RequiredAttribute属性上使用ID

关于DropDownListFor的第二个问题,尝试return View(viewModel)时会出现问题,因为在表单提交后UserReportViewModel.RequestType仍未分配,导致UserReportViewModel.RequestType集合中包含空值,并且构建ArgumentNullException时抛出SelectList

只要将List<RequestType>分配到现有的视图模型中,以防验证错误就足够了:

[HttpPost]
public ActionResult Save(UserReportViewModel viewModel)
{
    if (!ModelState.IsValid)
    {
        viewModel.RequestType = _context.RequestType.ToList(); // use this line instead

        return View("UserReportForm", viewModel); // change to return existing viewmodel
    }

    // other stuff - skipped for brevity

    return RedirectToAction("Report", "Report", new { stat = 1 });
}

答案 2 :(得分:0)

感谢您的回复,SAR和山本哲也-非常感谢您的建议!经过更多研究后,我得以解决我的问题。我发现的解决方案是如何使用视图模型。

首先,@ Html.ValidationSummary似乎将检查每个字段,以确定是否需要模型中定义的信息。就我而言,需要在报表模型 中定义的ID。在这种情况下,我可以通过简单地从我的观点中删除这一行来解决我的问题:

@Html.HiddenFor(m => m.Report.ID)

但是,我想使用此视图来创建表单和进行编辑。在这种情况下,我们需要将此ID设为可空。解决方案是编辑视图模型UserReportViewModel.cs,而不是编辑Report模型。我打开了这个文件,并添加了以下代码行:

public int? Id {get; set;}

然后,我回到我的视图并将其更改为:

@Html.HiddenFor(m => m.Id)

快完成了。回到控制器,我只需要稍微调整一下。 “新建”控制器中没有任何更改,但是在保存控制器中,我将使用viewModel.Report.ID的实例更改为viewModel.Id。我还在“ if(!ModelState.Valid)分支”中添加了一行代码。更新后的代码如下:

[HttpPost]
public ActionResult Save(UserReportViewModel viewModel)
{
    if (!ModelState.IsValid)
    {
        var viewM = new UserReportViewModel
        {
            RequestType = _context.RequestType.ToList(),
        };
        viewM.Id = viewModel.Report.ID;
        return View("UserReportForm", viewM);
    }
    if (viewModel.Id == 0)
    {
        _context.Reports.Add(viewModel.Report);
    }
    else
    {
        var reportInDb = _context.Reports.Single(c => c.ID == viewModel.Id);
        reportInDb.Name = viewModel.Report.Name;
        reportInDb.Description = viewModel.Report.Description;
        reportInDb.RequestTypeID = viewModel.Report.RequestTypeID;
    }
    _context.SaveChanges();
    return RedirectToAction("Report", "Report", new { stat = 1 });

}

这些更改之后,我能够通过验证成功创建和编辑表单!总之,解决此问题的方法是在视图模型中使用可为空的ID,而不是特定模型中的必需ID。