2017-03-11 51 views
0

我是MVC和jQuery的新手。以下問題涉及兩個表格Product和QuoteDetail。我正在使用DropDownListFor來允許用戶從產品表中選擇基於名稱的產品。一旦選擇名稱,QuoteDetail記錄中的兩個文本框將分別填充ProductId和Price。所有這一切都很好。我的問題是,當我保存QuoteDetail記錄時,它將ProductId保存在ProductName字段而不是ProductName中。我沒有看到我如何擺脫使用SelectList中的ProductId,因爲我需要它執行查找。我怎樣才能解決這個問題並保存ProductName?Dropdownlist選擇保存ID而不是名稱

這裏是DropDownListFor讀取方式:

@Html.DropDownListFor(model => model.ProductName, new SelectList(ViewBag.ProductData, "ProductId", "Name"), new { htmlAttributes = new { @id = "ProductName", @class = "ProductList" } }); 

jQuery的用於查找被如下:

<script type="text/javascript"> 
      $(document).ready(function() { 
       $(document).on("change", '[id*="ProductName"]', function() { 
        $.post("/QuoteViewModel/GetProduct", { pId: $(this).val() }, function (data) { 
         $("[id*='ProductId']").val(data.ProductId); 
         $("[id*='Price']").val(data.Price); 
        }); 
       }); 
       }); 
      </script> 

和用於查找所述控制器操作如下:

[HttpPost] 
     public ActionResult GetProduct(int pId) 
     { 
      var data = db.Products.Find(pId); 
      return Json(data); 
     } 

請注意,產品名稱在Product表格中稱爲「Name」,在QuoteDet中稱爲「ProductName」所有的桌子。任何幫助將非常感激。

用於保存代碼如下:

[HttpPost] 
     [ValidateAntiForgeryToken] 
     public ActionResult Edit(QuoteViewModel qvm,[Bind(Include = "CustomerId,SalesRep,FirstName,LastName,Company,Address1,Address2,City,State,PostalCode,WorkPhone,CellPhone,Email,Discount,PaymentTerms")] Customer customer, 
           [Bind(Include = "QuoteId,QuoteDetailId,ProductId,ProductName,Amount,ListPrice,Discount,Price")] List<QuoteDetail> quoteDetails, 
           [Bind(Include = "QuoteId,CustomerId,Subtotal,Tax,Total,QuoteDate,GoodUntil,QuoteSent,DateApproved,DateOrdered")] Quote quote) 

     { 

      if (ModelState.IsValid) 
      { 

       foreach (var quoteDetail in qvm.QuoteDetail) 
       { 

        QuoteDetail qd = db.QuoteDetails.FirstOrDefault(o => ((o.QuoteId == quoteDetail.QuoteId) && (o.QuoteDetailId == quoteDetail.QuoteDetailId))); 

        if (qd != null) 
        { 
         qd.ProductId = quoteDetail.ProductId; 
         qd.ProductName = quoteDetail.ProductName; 
         qd.Amount = quoteDetail.Amount; 
         qd.ListPrice = quoteDetail.ListPrice; 
         qd.Discount = quoteDetail.Discount; 
         qd.Price = quoteDetail.Price; 
        } 
        else 
        { 
         db.QuoteDetails.Add(quoteDetail); 
        } 

       } 

       quote.QuoteId = qvm.QuoteId; 
       quote.GoodUntil = qvm.GoodUntil; 
       quote.Discount = qvm.Discount; 
       quote.DateApproved = qvm.DateApproved; 
       quote.DateOrdered = qvm.DateOrdered; 
       quote.Discount = qvm.Discount; 
       quote.QuoteDate = qvm.QuoteDate; 
       quote.QuoteSent = qvm.QuoteSent; 
       quote.Subtotal = qvm.Subtotal; 
       quote.Tax = qvm.Tax; 
       quote.Total = qvm.Total; 

       customer.CustomerId = qvm.CustomerId; 
       customer.Address1 = qvm.Address1; 
       customer.Address2 = qvm.Address2; 
       customer.CellPhone = qvm.CellPhone; 
       customer.City = qvm.City; 
       customer.Company = qvm.Company; 
       customer.Discount = qvm.Discount; 
       customer.Email = qvm.Email; 
       customer.FirstName = qvm.FirstName; 
       customer.LastName = qvm.LastName; 
       customer.PaymentTerms = qvm.PaymentTerms; 
       customer.PostalCode = qvm.PostalCode; 
       customer.SalesRep = qvm.SalesRep; 
       customer.State = qvm.State; 
       customer.WorkPhone = qvm.WorkPhone; 

       db.Entry(quote).State = EntityState.Modified; 
       db.Entry(customer).State = EntityState.Modified; 

       bool saveFailed; 
       do 
       { 
        saveFailed = false; 
        try 
        { 
         db.SaveChanges(); 
        } 
        catch (DbUpdateConcurrencyException ex) 
        { 
         saveFailed = true; 
         var objContext = ((IObjectContextAdapter)db).ObjectContext; 
         // Get failed entry 
         var entry = ex.Entries.Single(); 
         // Now call refresh on ObjectContext 
         objContext.Refresh(RefreshMode.ClientWins, entry.Entity); 


        } 

       } while (saveFailed); 

       return RedirectToAction("Index"); 
      } 
      return View(qvm); 
     } 
    } 
} 

修訂DropDownListFor:

@Html.DropDownListFor(model => model.ProductName, new SelectList(ViewBag.ProductData, "ProductId", "Name"), new { htmlAttributes = new { name = "ProductId", @id = "ProductName", @class = "ProductList" } }); 
+0

請提供用於保存的代碼片段。 – codemirror

+0

請參閱上面的保存代碼。 –

回答

1

這是因爲當你提交一個表單,在所有相應的表單元素的值映射到包含它們的元素的name屬性,而不是id屬性。

你需要確保你明確地設置name屬性如預期的因素,以確保它們綁定正確的價值觀:

<!-- If you wanted the value from this bound as "ProductId", you would need to set the 
    name attribute in the htmlAttributes object --> 
@Html.DropDownListFor(model => model.ProductName, ..., new { ... name="ProductId" } }); 

根據您的需求,它可能會更容易根本就沒有讓你自己去DropDownList的任何更改,並允許它直接綁定到你的ProductId屬性,然後設置你的名字的時候你的AJAX調用完成:

@Html.DropDownListFor(model => model.ProductId, new SelectList(ViewBag.ProductData, "ProductId", "Name"), new { @class = "ProductList" } }); 

連同:

$(document).on("change", '[id*="ProductId"]', function() { 
    $.post("/QuoteViewModel/GetProduct", { pId: $(this).val() }, function (data) { 
     $("[id*='ProductId']").val(data.ProductId); 
     // This could be a hidden element within your form 
     $("[id*='ProductName']").val(data.ProductName); 
     $("[id*='Price']").val(data.Price); 
    }); 
}); 
+0

我嘗試了您提出的第一個解決方案,但我可能沒有做到正確。請參閱上面我發佈的代碼。 –

+0

第二種解決方案,允許它直接綁定到ProductId,打破查找。我認爲你告訴我正確的事情,但我不應該正確地執行它們。 –

+0

這是我的錯代碼,因爲你的事件處理程序應該在'ProductId'元素上監聽事件,因爲我已經更新了它。 –