我是MVC3的新手并尝试构建一个简单的Invoicing应用程序。我的代码的问题是Ajax Post失败了,我无法找到原因。逐步浏览JQuery代码似乎很好但是当POST命中控制器时,Model.IsValid为false。问题似乎与儿童记录有关。发票主记录正在保存到数据库,但InvoiceRow不存在。问题在于SaveInvoice()函数。
public class Invoice
{
[Key]
public int InvoiceID { get; set; }
public int ContractID { get; set; }
[Required]
[Display(Name = "Invoice Date")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public DateTime InvoiceDate { get; set; }
[Required]
[Display(Name = "Invoice No")]
public int InvoiceNumber { get; set; }
[Required(AllowEmptyStrings = true)]
[Display(Name = "Payment Date")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public DateTime PaymentDate { get; set; }
public virtual Contract Contract { get; set; }
public virtual ICollection<InvoiceRow> InvoiceRows { get; set; }
}
public class InvoiceRow
{
[Key]
public int Id { get; set; }
public int InvoiceID { get; set; }
public string RowDetail { get; set; }
public int RowQty { get; set; }
public decimal ItemPrice { get; set; }
public decimal RowTotal { get; set; }
public virtual Invoice Invoice { get; set; }
}
public class InvoiceController : Controller
{
private CyberneticsContext db = new CyberneticsContext();
//
// GET: /Invoice/
public ViewResult Index()
{
var invoices = db.Invoices.Include(i => i.Contract);
return View(invoices.ToList());
}
//
// GET: /Invoice/Details/5
public ViewResult Details(int id)
{
Invoice invoice = db.Invoices.Find(id);
return View(invoice);
}
//
// GET: /Invoice/Create
public ActionResult Create()
{
ViewBag.Title = "Create";
ViewBag.ContractID = new SelectList(db.Contracts, "Id", "ContractName");
return View();
}
//
// POST: /Invoice/Create
[HttpPost]
public JsonResult Create(Invoice invoice)
{
try
{
if (ModelState.IsValid)
{
if (invoice.InvoiceID > 0)
{
var invoiceRows = db.InvoiceRows.Where(ir => ir.InvoiceID == invoice.InvoiceID);
foreach (InvoiceRow row in invoiceRows)
{
db.InvoiceRows.Remove(row);
}
foreach (InvoiceRow row in invoice.InvoiceRows)
{
db.InvoiceRows.Add(row);
}
db.Entry(invoice).State = EntityState.Modified;
}
else
{
db.Invoices.Add(invoice);
}
db.SaveChanges();
return Json(new { Success = 1, InvoiceID = invoice.InvoiceID, ex = "" });
}
}
catch (Exception ex)
{
return Json(new { Success = 0, ex = ex.Message.ToString() });
}
return Json(new { Success = 0, ex = new Exception("Unable to Save Invoice").Message.ToString() });
}
//
// GET: /Invoice/Edit/5
public ActionResult Edit(int id)
{
ViewBag.Title = "Edit";
Invoice invoice = db.Invoices.Find(id);
ViewBag.ContractID = new SelectList(db.Contracts, "Id", "ContractName", invoice.ContractID);
return View("Create", invoice);
}
//
// POST: /Invoice/Edit/5
[HttpPost]
public ActionResult Edit(Invoice invoice)
{
if (ModelState.IsValid)
{
db.Entry(invoice).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ContractID = new SelectList(db.Contracts, "Id", "ContractName", invoice.ContractID);
return View(invoice);
}
//
// GET: /Invoice/Delete/5
public ActionResult Delete(int id)
{
Invoice invoice = db.Invoices.Find(id);
return View(invoice);
}
//
// POST: /Invoice/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Invoice invoice = db.Invoices.Find(id);
db.Invoices.Remove(invoice);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
@model Cybernetics2012.Models.Invoice
... script tags excluded for brevity
<h2 class="h2">@ViewBag.Title</h2>
<script type="text/javascript">
$( document ).ready( function ()
{
// here i have used datatables.js (jQuery Data Table)
$( '.tableItems' ).dataTable
(
{
"sDom": 'T<"clear">lfrtip',
"oTableTools": { "aButtons": [], "sRowSelect": "single" },
"bLengthChange": false,
"bFilter": false,
"bSort": true,
"bInfo": false
}
);
// Add DatePicker widget to InvoiceDate textbox
$( '#InvoiceDate' ).datepicker();
// Add DatePicker widget to PaymentDate textbox
$( '#PaymentDate' ).datepicker();
// Get the tableItems table
var oTable = $( '.tableItems' ).dataTable();
} );
// this function is used to add item to table
function AddInvoiceItem()
{
// Adding item to table
$( '.tableItems' ).dataTable().fnAddData( [$( '#RowDetail' ).val(), $( '#RowQty' ).val(), $( '#ItemPrice' ).val(), $( '#RowQty' ).val() * $( '#ItemPrice' ).val()] );
// clear text boes after adding data to table..
$( '#RowDetail' ).val( "" )
$( '#RowQty' ).val( "" )
$( '#ItemPrice' ).val( "" )
}
// This function is used to delete selected row from Invoice Rows Table and then set deleted item to Edit text Boxes
function DeleteRow()
{
// DataTables.TableTools plugin for getting selected row items
var oTT = TableTools.fnGetInstance( 'tableItems' ); // Get Table instance
var sRow = oTT.fnGetSelected(); // Get Selected Item From Table
// Set deleted row item to editable text boxes
$( '#RowDetail' ).val( $.trim( sRow[0].cells[0].innerHTML.toString() ) );
$( '#RowQty' ).val( jQuery.trim( sRow[0].cells[1].innerHTML.toString() ) );
$( '#ItemPrice' ).val( $.trim( sRow[0].cells[2].innerHTML.toString() ) );
$( '.tableItems' ).dataTable().fnDeleteRow( sRow[0] );
}
//This function is used for sending data(JSON Data) to the Invoice Controller
function SaveInvoice()
{
// Step 1: Read View Data and Create JSON Object
// Creating invoicRow Json Object
var invoiceRow = { "InvoiceID": "", "RowDetail": "", "RowQty": "", "ItemPrice": "", "RowTotal": "" };
// Creating invoice Json Object
var invoice = { "InvoiceID": "", "ContractID": "", "InvoiceDate": "", "InvoiceNumber": "", "PaymentDate": "", "InvoiceRows":[] };
// Set Invoice Value
invoice.InvoiceID = $( "#InvoiceID" ).val();
invoice.ContractID = $( "#ContractID" ).val();
invoice.InvoiceDate = $( "#InvoiceDate" ).val();
invoice.InvoiceNumber = $( "#InvoiceNumber" ).val();
invoice.PaymentDate = $( "#PaymentDate" ).val();
// Getting Table Data from where we will fetch Invoice Rows Record
var oTable = $( '.tableItems' ).dataTable().fnGetData();
for ( var i = 0; i < oTable.length; i++ )
{
// IF This view is for edit then it will read InvoiceId from Hidden field
if ( $( 'h2' ).text() == "Edit" )
{
invoiceRow.InvoiceID = $( '#InvoiceID' ).val();
}
else
{
invoiceRow.InvoiceID = 0;
}
// Set InvoiceRow individual Value
invoiceRow.RowDetail = oTable[i][0];
invoiceRow.RowQty = oTable[i][1];
invoiceRow.ItemPrice = oTable[i][2];
invoiceRow.RowTotal = oTable[i][3];
// adding to Invoice.InvoiceRow List Item
invoice.InvoiceRows.push( invoiceRow );
invoiceRow = { "RowDetail": "", "RowQty": "", "ItemPrice": "", "RowTotal": "" };
}
// Step 1: Ends Here
// Set 2: Ajax Post
// Here i have used ajax post for saving/updating information
$.ajax( {
url: '/Invoice/Create',
data: JSON.stringify( invoice ),
type: 'POST',
contentType: 'application/json;',
dataType: 'json',
success: function ( result )
{
if ( result.Success == "1" )
{
window.location.href = "/Invoice/Index";
}
else
{
alert( result.ex );
}
}
} );
}
</script>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Invoice</legend>
@if (Model != null)
{
<input type="hidden" id="InvoiceID" name="InvoiceID" value="@Model.InvoiceID" />
}
<div class="editor-label">
@Html.LabelFor(model => model.ContractID, "Contract")
</div>
<div class="editor-field">
@Html.DropDownList("ContractID", String.Empty)
@Html.ValidationMessageFor(model => model.ContractID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.InvoiceDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.InvoiceDate)
@Html.ValidationMessageFor(model => model.InvoiceDate)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.InvoiceNumber)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.InvoiceNumber)
@Html.ValidationMessageFor(model => model.InvoiceNumber)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.PaymentDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.PaymentDate)
@Html.ValidationMessageFor(model => model.PaymentDate)
</div>
</fieldset>
<br />
<fieldset>
<legend>Add Invoice Row</legend>
<br />
<label>
Row Detail :</label>
@Html.TextBox("RowDetail")
<label>
Row Qty :</label>
@Html.TextBox("RowQty", null, new { style = "width:20px;text-align:center" })
<label>
Item Price :</label>
@Html.TextBox("ItemPrice", null, new { style = "width:70px" })
<input onclick="AddInvoiceItem()" type="button" value="Add Invoice Item" />
<table id="tableItems" class="tableItems" width="400px">
<thead>
<tr>
<th>
Detail
</th>
<th>
Qty
</th>
<th>
Price
</th>
<th>
Row Total
</th>
</tr>
</thead>
<tbody>
@if (Model != null)
{
foreach (var item in Model.InvoiceRows)
{
<tr>
<td>
@Html.DisplayFor(i => item.RowDetail)
</td>
<td>
@Html.DisplayFor(i => item.RowQty)
</td>
<td>
@Html.DisplayFor(i => item.ItemPrice)
</td>
<td>
@Html.DisplayFor(i => item.RowTotal)
</td>
</tr>
}
}
</tbody>
</table>
<br />
<input onclick="DeleteRow()" type="button" value="Delete Selected Row" />
</fieldset>
<p>
<input onclick="SaveInvoice()" type="submit" value="Save Invoice" />
</p>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
答案 0 :(得分:0)