ASP.NET MVC - POST ViewModel 中的空对象

ASP.NET MVC - Null Object in ViewModel on POST

在 ActionController 的 POST 上,我收到了很棒的 ole' 对象引用未设置为对象的实例 错误。

基本上我需要将 userRequest 的 ID 与 requestResponse 一起保存。 (这里是外键)

这是代码。

ViewModel:

public class RequestResponseViewModel
{
    public Models.Request userRequest { get; set; }

    public Models.RequestResponse requestResponse { get; set; }

}

查看: 在调试中 model.userRequest.ID

中有值
    @model UserRequests.ViewModels.RequestResponseViewModel

  @{
    ViewBag.Title = "Create";
  }

  <h2>Admin Response to Request</h2>

  @using (Html.BeginForm())
  {
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.requestResponse.Response, 
  htmlAttributes: new { @class = "control-label col-md-1" })
            <div class="col-md-10">
                @Html.TextAreaFor(model => model.requestResponse.Response, new { 
  @class = "form-control", @rows = 5 })
                @Html.ValidationMessageFor(model => 
  model.requestResponse.Response, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
              @Html.LabelFor(model => model.userRequest.ID, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-2">

                @Html.DisplayFor(model => model.userRequest.ID)             
                @Html.ValidationMessageFor(model => model.userRequest.ID, "", new { @class = "text-danger" })
            </div>
            @Html.LabelFor(model => model.requestResponse.Author, htmlAttributes: new { @class = "control-label col-md-1" })
            <div class="col-md-3">
                @Html.EditorFor(model => model.requestResponse.Author, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.requestResponse.Author, "", new { @class = "text-danger" })
            </div>
            @Html.LabelFor(model => model.requestResponse.CreateDate, htmlAttributes: new { @class = "control-label col-md-1" })
            <div class="col-md-3">
                <h5>@DateTime.Now</h5>
                @Html.ValidationMessageFor(model => model.requestResponse.CreateDate, "", new { @class = "text-danger" })
            </div>
        </div>



        <div class="form-group">
            <div class="col-md-offset-1">
                <button type="reset" class="btn btn-default">Cancel</button>
                <input type="submit" value="Create" class="btn btn-success" />
            </div>
        </div>
    </div>

    <hr />
    <h3 class="text-success">Original Request</h3>
    <div class="row">
        <div class="col-md-10">
          <h4>@Html.DisplayFor(model => model.userRequest.Title)</h4>
        </div>
    </div>

    <div class="row">
        <div class="col-md-10">
            <h4>@Html.DisplayFor(model => model.userRequest.Description)</h4>
        </div>
    </div>

    }

    <div>
      @Html.ActionLink("Back to Browse", "Browse","Change")
    </div>

获取操作结果:

public ActionResult Create(int id)
    {


        UserRequestContextDataContext db = new UserRequestContextDataContext();
        var request = (from m in db.Requests
                       where m.ID == id
                       select new Models.Request()
                       {

                           ID = m.ID,
                           Title = m.Title,
                           Description = m.Description,
                           BusinessUnit = m.BusinessUnit,
                           Author = m.Author,
                           ModuleName = m.MenuItem,
                           RequestStatus = 2,
                           SubmitDate = m.SubmitDate,
                           Type = m.Type,
                           UrgencyNum = m.UrgencyLevel


                       }).FirstOrDefault();

        var reqResponse = new Models.RequestResponse();


        var viewModel = new RequestResponseViewModel
        {
            userRequest = request,
            requestResponse = reqResponse

        };

        return View(viewModel);
    }

这里的"viewModel"有我需要的一切。它丢失在 ActionResults 之间的某处..

最后 Post ActionResult:

 [HttpPost]
    public ActionResult Create(RequestResponseViewModel _requestResponseViewModel) 
    {
        try
        {

            if (ModelState.IsValid)
            {
                using (UserRequestContextDataContext db = new UserRequestContextDataContext())
                {

                    RequestResponse reqRes = new RequestResponse();
                    reqRes.Response = _requestResponseViewModel.requestResponse.Response.ToString();

                    reqRes.RequestID = _requestResponseViewModel.userRequest.ID;
                    reqRes.Author = _requestResponseViewModel.requestResponse.Author.ToString();
                    reqRes.CreateDate = DateTime.Now;

                    db.RequestResponses.InsertOnSubmit(reqRes);
                    db.SubmitChanges();
                }
            }

            return RedirectToAction("Browse","Change");
        }
        catch (Exception ex)
        {

            return View("Error", new HandleErrorInfo(ex, "Change", "Create"));
        }
    }

使用调试模式,userRequest 对象在 POST 方法的视图模型参数中为 NULL,但 requestResponse 为 FINE 并按应有的方式填充。

对此进行搜索,似乎大部分问题都与视图模型中的命名约定有关,但我已确保那里没有差异。

如果有更清晰的方法来完成此工作流程,请提及。

@Html.DisplayFor 不会创建 HTML 输入元素,而是创建一个简单的字符串文字(对于大多数类型,文档中列出了一些例外情况:https://msdn.microsoft.com/en-us/library/ee407420(v=vs.118).aspx#Anchor_1)。 因此,当您按下提交时,您的浏览器不会将 ID 发送回服务器,因为它只发送表单数据(例如来自输入、textare、select 字段的数据)。使用浏览器开发人员工具 (F12),您可以检查实际发送到服务器的内容。

您可以使用@Html.HiddenFor(model => model.userRequest.ID)添加隐藏输入框,或使用ID的自定义显示模板自动添加隐藏输入框。您可以进一步使用 UIHint 属性自动 select 显示模板。这两种方法都有详尽的记录(例如 http://www.codeguru.com/csharp/.net/net_asp/mvc/using-display-templates-and-editor-templates-in-asp.net-mvc.htm)。

对象在 POST 中可能为 NULL 的另一个原因是忘记添加设置器 { get;放; } 在你的视图模型中:

public 订单订单; --> 缺少 { 得到;放; }

public class OrderViewModel
{
    public Orders orders { get; set; }

    public List<VendorJobTitleView> Jobs { get; set; }

    public List<ManagerView> Managers { get; set; }


}