2016-01-22 24 views
-1

我有一個非常簡單的問題,可能有一個非常簡單的答案,但是,我無法解決它。ASP.NET MVC從視圖返回的空對象

我有如下視圖模型:

namespace CommunicationsLog.ViewModels 
{ 
    public class CommunicationViewModel 
    { 
     public Communication Communication { get; set; } 
     public Feedback Feedback { get; set; } 
     public IEnumerable<Resolution> Resolutions { get; set; } 
    } 
} 

我試圖從我的Add.cshtml頁面創建一個溝通的新實例:

@model CommunicationsLog.ViewModels.CommunicationViewModel 
@{ 
    ViewBag.Title = "Add"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
@using (Html.BeginForm("Add", "Communication")) 
{ 
    <div class="form-horizontal" id="addForm"> 
     <div class="row"> 
      <div class="col-md-12"> 
       @Html.ValidationSummary(true, "", new { @class="text-danger"}) 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.Customer.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @if (Model.Communication.Customer.Name == null) 
         { 
          <input id="btnCust" type="button" value="Select Customer" class="btn btn-default addCustomer" /> 
         } 
         else 
         { 
          <span id="custSpan" style="font-size:16px; font:bold;"> 
           @Html.DisplayFor(model => model.Communication.Customer.Name) 
           <input id="btnEditCust" type="button" value="Edit" class="btn btn-default addCustomer"/> 
          </span> 
         } 
        <div id="addCust"></div> 
       </div> 
      </div> 
     </div> 
    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input id="btnSubmit" type="submit" value="Create" class="btn btn-default" /> 
     </div> 
    </div> 
} 
<div> 
    @Html.ActionLink("Back to Communications", "Index") 
</div> 

在提交此調用下面控制器操作:

[HttpPost] 
    public ActionResult Add(CommunicationViewModel viewModel) 
    { 
     callEnd = DateTime.Now; 
     var totalCallTime = callEnd - callStart; 
     Communication insertedComm = null; 
     try 
     { 
      Communication comm = viewModel.Communication; 
      comm.CallTime = totalCallTime.ToString(@"mm\:ss"); 
      var customer = _uow.CustomerRepository.Get() 
               .Where(c => c.Name == comm.Customer.Name); 
      comm.CustomerId = customer.FirstOrDefault().CustomerId; 
      comm.Customer = customer.FirstOrDefault(); 
      comm.State = "Open"; 
      if (ModelState.IsValid) 
      { 
       insertedComm = _uow.CommunicationRepository.Insert(comm); 
       _uow.Save(); 

      } 

      Feedback feedback = viewModel.Feedback; 
      if (feedback.Type != null && feedback.Notes != null) 
      { 
       feedback.Communication = insertedComm; 
       feedback.CommunicationId = insertedComm.CommunicationId; 
       var insertedFB = _uow.FeedbackRepository.Insert(feedback); 
       _uow.Save(); 
      } 

      return RedirectToAction("Index"); 
     } 
     catch (Exception e) 
     { 
      if(viewModel.Communication == null) 
      { 
       viewModel.Communication = new Communication(); 
      }     
      return View(viewModel); 
     } 
    } 

但是,當viewModel加載到控制器操作時,通信對象爲空。反饋對象已成功實例化。

調試後,我發現視圖模型正確實例化,並且在頁面加載時不爲null,並且通過預定義的數據正確顯示。它似乎只是失去了POST請求的價值。

任何人都可以幫忙嗎?

非常感謝,

編輯:

正如指出的評論其實我已刪除了我的片段,使這裏的重要組成部分,是不包括JavaScript作爲不相關的POST請求的完整視圖:

@model CommunicationsLog.ViewModels.CommunicationViewModel 
@{ 
    ViewBag.Title = "Add"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
<h2>Add</h2> 
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"> 
<script src="//code.jquery.com/jquery-1.10.2.js"></script> 
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 
@using (Html.BeginForm("Add", "Communication")) 
{ 
    <div class="form-horizontal" id="addForm"> 
     <h4>Communication</h4> 
     <div id="countdown" class="countdownHolder"></div> 
     <hr/> 
     <div class="row"> 
      <div class="col-md-12"> 
       @Html.ValidationSummary(true, "", new { @class="text-danger"}) 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.Customer.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @if (Model.Communication.Customer.Name == null) 
         { 
          <input id="btnCust" type="button" value="Select Customer" class="btn btn-default addCustomer" /> 
         } 
         else 
         { 
          <span id="custSpan" style="font-size:16px; font:bold;"> 
           @Html.DisplayFor(model => model.Communication.Customer.Name) 
           <input id="btnEditCust" type="button" value="Edit" class="btn btn-default addCustomer"/> 
          </span> 
         } 
         <div id="addCust"></div> 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.Receiver, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @Html.EditorFor(model => model.Communication.Receiver, new { htmlAttributes = new { @class = "form-control" } }) 
         @Html.ValidationMessageFor(model => model.Communication.Receiver, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.Department, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @Html.EditorFor(model => model.Communication.Department, new { htmlAttributes = new { @class = "form-control" } }) 
         @Html.ValidationMessageFor(model => model.Communication.Department, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.CommDateTime, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         <span id="custSpan" style="font-size:14px;"> 
          @Html.DisplayFor(model => model.Communication.CommDateTime) 
         </span> 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.Method, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @Html.EditorFor(model => model.Communication.Method, new { htmlAttributes = new { @class = "form-control" } }) 
         @Html.ValidationMessageFor(model => model.Communication.Method, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.Product, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @Html.EditorFor(model => model.Communication.Product, new { htmlAttributes = new { @class = "form-control" } }) 
         @Html.ValidationMessageFor(model => model.Communication.Product, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.PartNo, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @Html.EditorFor(model => model.Communication.PartNo, new { htmlAttributes = new { @class = "form-control" } }) 
         @Html.ValidationMessageFor(model => model.Communication.PartNo, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.LabelFor(model => model.Communication.Description, htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         @Html.EditorFor(model => model.Communication.Description, new { htmlAttributes = new { @class = "form-control" } }) 
         @Html.ValidationMessageFor(model => model.Communication.Description, "", new { @class = "text-danger" }) 
        </div> 
       </div> 
       <div class="form-group"> 
        @Html.Label("Feedback?", htmlAttributes: new { @class = "control-label col-md-2" }) 
        <div class="col-md-10"> 
         <input type="checkbox" id="chkFeedback" name="chkFeedback" onclick="showFeedbackForm(this)"/> 
        </div> 
       </div> 
       <div id="feedbackForm" style="display:none"> 
        <div class="form-group"> 
         @Html.LabelFor(model => model.Feedback.Type, htmlAttributes: new { @class = "control-label col-md-2" }) 
         <div class="col-md-10"> 
          @Html.EditorFor(model => model.Feedback.Type, new { htmlAttributes = new { @class = "form-control" } }) 
          @Html.ValidationMessageFor(model => model.Feedback.Type, "", new { @class = "text-danger" }) 
         </div> 
        </div> 
        <div class="form-group"> 
         @Html.LabelFor(model => model.Feedback.Notes, htmlAttributes: new { @class = "control-label col-md-2" }) 
         <div class="col-md-10"> 
          @Html.EditorFor(model => model.Feedback.Notes, new { htmlAttributes = new { @class = "form-control" } }) 
          @Html.ValidationMessageFor(model => model.Feedback.Notes, "", new { @class = "text-danger" }) 
         </div> 
        </div> 
       </div> 
      </div> 
     </div> 
    </div> 
    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input id="btnSubmit" type="submit" value="Create" class="btn btn-default" /> 
     </div> 
    </div> 
} 
<div> 
    @Html.ActionLink("Back to Communications", "Index") 
</div> 

我不知道是否有幫助,但這裏是從VS全堆棧跟蹤:

Object reference not set to an instance of an object.  
    at ASP._Page_Views_Communication_Add_cshtml.Execute() in C:\Projects\CommunicationsLog\CommunicationsLog\Views\Communication\Add.cshtml:line 24 
    at System.Web.WebPages.WebPageBase.ExecutePageHierarchy() 
    at System.Web.Mvc.WebViewPage.ExecutePageHierarchy() 
    at System.Web.WebPages.StartPage.RunPage() 
    at System.Web.WebPages.StartPage.ExecutePageHierarchy() 
    at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) 
    at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) 
    at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) 
    at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) 
    at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) 
    at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) 
    at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) 
+0

由於MVC無法找到任何要綁定的東西,因此您沒有約束任何東西。我看到displayfor和labels,但你的輸入在哪裏? – Chad

+0

抱歉,我已經更新了我的問題全景 – DaRoGa

+0

如果刪除@ Html.HiddenFor(model => model.Communication),會發生什麼情況? –

回答

1

由於您使用的標記,任何<input>標籤都需要有一個名字定義的輸入名稱/值對被回傳到服務器:

<input name="@Html.NameFor(i => i.Communication.Customer.Name)" ... /> 

然後模型將被填充。您還可以使用:

@Html.TextBoxFor(i => i.Communication.Customer.Name) 

所有的輸入都需要這個。我也看到你的價值屬性包含「選擇客戶」;這將回發到服務器。如果使用placeholder="Select Customer",則此值不會發布到服務器,但仍會在文本框爲空時顯示。

+0

工作方式是,如果沒有客戶進行通信,那麼只會顯示一個按鈕,它將加載一個對話框,供您選擇一個客戶,然後重新加載具有正確詳細信息的添加視圖(這一切都有效)客戶被選中,然後它在顯示器上顯示該名稱並顯示編輯按鈕。所以你可以澄清哪些輸入我需要改變,以及如何在當前,客戶名稱顯示爲不是在輸入。對不起,如果我失去了一些東西,而且很天真 – DaRoGa

+0

@DaRoGa你不是天真的;你在這裏有一個複雜的設置。我真的不知道我的理解足夠引導你。但是你必須理解MVC模型綁定數據的規則。所以它使用了一個通過使用Html.NameFor(i => i.Communication.Customer.Name)助手將輸入的名稱映射到模型的約定,該助手爲客戶端生成了類似Communcation__Customer__Name的東西(這不是100%正確的... ),所以MVC然後使用這個約定來重新綁定一個嵌套模型。 MVC沒有看到任何這樣的輸入返回到服務器,因此您的模型爲空。 –

+0

你的挑戰是弄清楚什麼你需要發送到服務器何時何地,在形式....我注意到沒有你的標籤沒有名稱屬性,所以當一個職位發生時,什麼都不是通過POST操作發送到服務器.... –