2017-04-18 106 views
0

我是MVC的新手。我有一個父視圖,可以讓用戶爲客戶創建報價。一個AJAX鏈接,「添加產品」加載一個局部視圖「EditQuoteDetail」,使用戶可以將產品添加到報價中。問題是,如果ModelState在POST上無效(例如用戶忘記輸入所需的電話號碼),則產品的部分視圖不會返回到視圖。我必須做什麼才能將QuoteDetails返回給用戶?如果模型狀態無效,部分視圖不被保留

這裏是主視圖:

@model CMSUsersAndRoles.Models.QuoteViewModel 

@{ 
    ViewBag.Title = "Create"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
@Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js") 

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
<script src="~/Scripts/jquery.mask.min.js"></script> 

<h2>Create</h2> 

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

    <div class="form-horizontal"> 
     <h4>Quote</h4> 
     <hr /> 
     <div class="form-group"> 
      <div class="col-md-10"> 
       @Html.HiddenFor(model => model.QuoteId) 
      </div> 
     </div> 
<div class="form-group"> 
      @Html.LabelFor(model => model.Company, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-10"> 
       @Html.DropDownListFor(model => model.CustomerId, new SelectList(ViewBag.Customers, "CustomerId", "Company"), "---Select one---", new { style = "width: 300px !important", htmlAttributes = new { @class = "company" } }); 
       @Html.HiddenFor(model => model.Company, new { @class = "companyName" }) 
       @Html.ValidationMessageFor(model => model.Company, "", new { @class = "text-danger" }) 

      </div> 
     </div> 

... //other Quote fields 

<div class="form-group"> 
      @Html.LabelFor(model => model.QuoteDetail, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-10" id="QuoteDetails"> 
       @Html.ValidationMessageFor(model => model.QuoteDetail, "", new { @class = "text-danger"}) 

@Ajax.ActionLink("Add product", "AddProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetail.Count + 1) }, new AjaxOptions 
      { 
       UpdateTargetId = "QuoteDetails", 
       InsertionMode = InsertionMode.InsertBefore 
      }) 

      </div> 

下面是部分視圖:

@model CMSUsersAndRoles.Models.QuoteDetail 

@{ 
    ViewBag.Title = "EditQuoteDetail"; 
    Layout = null; 
} 


    <div id="row" class="row"> 
     <table> 

      @using (Html.BeginCollectionItem("quoteDetail")) 

      { 

       <tr> 
        @Html.HiddenFor(model => model.QuoteId, new { htmlAttributes = new { @class = "form-control" } }) 
        @Html.HiddenFor(model => model.QuoteDetailId, new { htmlAttributes = new { @class = "form-control" } }) 
        @Html.EditorFor(model => model.SKU, new { htmlAttributes = new { @readonly = "readonly", @id = "SKU", @class = "form-control", style = "width: 100px" } }) 
        @Html.DropDownListFor(model => model.ProductId, new SelectList(ViewBag.ProductData, "ProductId", "Name"), "---Select one---", new { style = "width: 300px !important", required = "required", htmlAttributes = new { @id = "ProductName", @class = "ProductList" } }) 
        @Html.HiddenFor(model => model.ProductName) 

        @Html.EditorFor(model => model.Amount, new { htmlAttributes = new { @id = "Amt", @class = "form-control amount", style = "width: 95px" } }) 
        @Html.EditorFor(model => model.ListPrice, new { htmlAttributes = new { @readonly = "readonly", @id = "LPrce", @class = "form-control listprice", style = "width: 95px" } }) 
        @Html.EditorFor(model => model.Discount, new { htmlAttributes = new { @id = "TotalDiscount", @class = "form-control discount", style = "width: 100px" } }) 
        @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @readonly = "readonly", @id = "FinalPrce", @class = "form-control price", style = "width: 100px" } }) 


        @Ajax.ActionLink(" ", "DeleteProduct", "QuoteViewModel", new { quoteId = Model.QuoteId, quoteDetailId = (Model.QuoteDetailId) }, 
          new AjaxOptions 
          { 
           HttpMethod = "POST", 
           Confirm = "Are you Sure You Want to Delete " + Model.ProductName, 
           OnSuccess = "RemoveRow" 
          }, 
          new { @class = "btn btn-danger glyphicon glyphicon-trash" }) 
       </tr> 
      } 

     </table> 
    </div> 

這裏是POST:

[HttpPost] 
     [ValidateAntiForgeryToken] 
     public ActionResult Create(QuoteViewModel qvm) 
     { 
      if (qvm.QuoteDetail == null) 
      { 
       qvm.QuoteDetail = new List<QuoteDetail>(); 
       qvm.QuoteDetail.Add(new QuoteDetail() { QuoteId = qvm.QuoteId, QuoteDetailId = (qvm.QuoteDetail.Count + 1) }); 
       var customerList = db.Customers.ToList(); 
       ViewBag.Customers = customerList; 
       return View(qvm); 
      } 

      if (ModelState.IsValid) 
      { 

      ... //process 

return RedirectToAction("Index"); 
      } 

      var customers = db.Customers.ToList(); 
      ViewBag.Customers = customers; 

      return View(qvm); 
     } 

這裏是加載的局部代碼查看:

public ActionResult AddProduct(int quoteId, int quoteDetailId) 
     { 
      var items = db.Products.ToList(); 
      ViewBag.ProductData = items; 

      return PartialView("EditQuoteDetail", new QuoteDetail { QuoteId = quoteId, QuoteDetailId = quoteDetailId }); 
     } 

這裏是視圖模型的相關章節:

public class QuoteViewModel 
    { // Columns from QuoteDetail table 
     [Required(ErrorMessage ="Please add product(s) to quote ")] 
     [Display(Name = "Quote Detail")] 
     public List<QuoteDetail> QuoteDetail { get; set; } 
    } 

我缺少什麼?任何幫助都感激不盡。

+0

你需要證明你的'QuoteViewModel模型' - 它是否包含一個名爲'quoteDetail'的屬性,它是'QuoteDetail'的集合? –

+0

@StephenMuecke,上面添加。 –

回答

1

您的主視圖需要包含一個循環來爲任何現有的QuoteDetail(其中包括您動態添加的那些)生成html。

在您的GET方法或QuoteViewModel的默認構造函數中,請確保將QuoteDetail初始化爲新集合,而不是null。然後在視圖中,添加以下代碼

@foreach(var detail in Model.QuoteDetail) 
{ 
    @Html.Partial("EditQuoteDetail", detail) 
} 

作爲一個側面說明,你應該使用一個視圖模型爲QuoteDetail,它不應該包括財產QuoteId

+0

謝謝!這解決了這個問題。 –

相關問題