public class UserDetailsModel
{
public int ID { get; set; }
public string LoginID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string IsDeleted { get; set; }
public DateTime CreatedOn { get; set; }
}
Controller:
public ActionResult Index()
{
object model = obj.getUserList();
return View(model);
}
public ActionResult Delete(int id)
{
BAL_obj.deleteUser(id);
object model = obj.getUserList();
return View("Index",model);
}
Index.cshtml:
#model IEnumerable<WebGrid1App.Models.UserDetailsModel>
#{
WebGrid grid = new WebGrid(Model);
}
<h2>People</h2>
#grid.GetHtml(
headerStyle: "headerStyle",
tableStyle: "tableStyle",
alternatingRowStyle: "alternateStyle",
fillEmptyRows: true,
mode: WebGridPagerModes.All,
firstText: "<< First",
previousText: "< Prev",
nextText: "Next >",
lastText: "Last >>",
columns: new [] {
grid.Column("ID",header: "ID"),
grid.Column("LoginId",header:"LoginID"),
grid.Column("FirstName", canSort: false),
grid.Column("LastName"),
grid.Column("CreatedOn",
header: "CreatedOn",
format: p=>p.CreatedOn.ToShortDateString()
),
grid.Column("",
header: "Actions",
format: #<text>
#Html.ActionLink("Edit", "Edit", new { id=item.ID} )
|
#Html.ActionLink("Delete", "Delete", new { id=item.ID} )
</text>
)
})
I have done with the delete operation.
How can I edit a row on same page and save the changes into database?
There will edit button. When you click on it, row will be editable.
Meanwhile edit link text is changed as Save link.
Now when you click on Save, row needs to be updated.
I want to do Inline editing.
Can you please help me out with this?
You could use AJAX. Start by wrapping the webGrid into an html form which will allow for editing the record:
#using (Html.BeginForm("Update", null, FormMethod.Post, new { #class = "updateForm" }))
{
#grid.GetHtml(
headerStyle: "headerStyle",
tableStyle: "tableStyle",
alternatingRowStyle: "alternateStyle",
fillEmptyRows: true,
mode: WebGridPagerModes.All,
firstText: "<< First",
previousText: "< Prev",
nextText: "Next >",
lastText: "Last >>",
columns: new[]
{
grid.Column("ID",header: "ID"),
grid.Column("LoginId",header:"LoginID"),
grid.Column("FirstName", canSort: false),
grid.Column("LastName"),
grid.Column("CreatedOn",
header: "CreatedOn",
format: p=>p.CreatedOn.ToShortDateString()
),
grid.Column("",
header: "Actions",
format: #<text>
#Html.ActionLink("Edit", "Edit", new { id = item.ID }, new { #class = "edit" })
|
#Html.ActionLink("Delete", "Delete", new { id = item.ID })
</text>
)
}
)
}
Then you could have 2 partials, one for editing and one for displaying a single record.
EditUserDetailsModel.cshtml:
#model UserDetailsModel
<td>#Html.EditorFor(x => x.ID)</td>
<td>#Html.EditorFor(x => x.LoginID)</td>
<td>#Html.EditorFor(x => x.FirstName)</td>
<td>#Html.EditorFor(x => x.LastName)</td>
<td>#Html.EditorFor(x => x.CreatedOn)</td>
<td>
<button type="submit">Update</button>
</td>
DisplayUserDetailsModel:
#model UserDetailsModel
<td>#Html.DisplayFor(x => x.ID)</td>
<td>#Html.DisplayFor(x => x.LoginID)</td>
<td>#Html.DisplayFor(x => x.FirstName)</td>
<td>#Html.DisplayFor(x => x.LastName)</td>
<td>#Html.DisplayFor(x => x.CreatedOn)</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = Model.ID }, new { #class = "edit" })
|
#Html.ActionLink("Delete", "Delete", new { id = Model.ID })
</td>
and then we could have the corresponding controller actions:
public ActionResult Edit(int id)
{
UserDetailsModel model = repository.Get(id);
return PartialView("EditUserDetailsModel", model);
}
[HttpPost]
public ActionResult Update(UserDetailsModel model)
{
repository.Update(model);
return PartialView("DisplayUserDetailsModel", model);
}
and finally the javascript to make this alive:
$('table').on('click', '.edit', function () {
$.ajax({
url: this.href,
type: 'GET',
cache: false,
context: $(this).closest('tr'),
success: function (result) {
$(this).html(result);
}
});
return false;
});
$('.updateForm').on('submit', function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
context: $('input', this).closest('tr'),
success: function (result) {
$(this).html(result);
}
});
return false;
});
The answer using ajax works fine - but you have to be aware that here multiple lines can be simultaneuously in edit mode.
A solution allowing only editing of one line (with less ajax requests) is:
http://www.c-sharpcorner.com/UploadFile/cd7c2e/create-an-editable-webgrid-in-mvc4-to-implement-crud-operati/
Related
I have two controls Speed and Speed unit. Speed is a numeric textbox and Speed unit is a dropdown.
The speed field is required if speed unit is filled in and visa versa.
To achieve this validation I'm using the remote data annotation. However in the front-end the validation is not triggering.
My viewmodel:
[AbpDisplayName(OE_TenantConsts.LocalizationSourceName, "idb_Incident.Speed")]
[Range(0.0, double.MaxValue, ErrorMessage = "Please enter a value of {1} or more")]
[Remote(action: "VerifySpeedAndUnit", controller: "Event", AdditionalFields = nameof(SpeedUnitId))]
public decimal? Speed { get; set; }
[AbpDisplayName(OE_TenantConsts.LocalizationSourceName, "idb_Incident.SpeedUnitId")]
[Remote(action: "VerifySpeedAndUnit", controller: "Event", AdditionalFields = nameof(Speed))]
public int? SpeedUnitId { get; set; }
My controller (event controller -> VerifySpeedAndUnit):
[AcceptVerbs("GET", "POST")]
[AllowAnonymous]
public IActionResult VerifySpeedAndUnit(decimal? speed, int? speedUnitId)
{
if ((speed.HasValue && speedUnitId == DropdownConstants.DefaultSelectedSpeedUnitId) || (speed.HasValue && speedUnitId == null))
{
return Json("When entering a speed, you need to select the speed scale as well.");
}
if (speedUnitId != DropdownConstants.DefaultSelectedSpeedUnitId && speed.HasValue && speedUnitId != null)
{
return Json("When selecting a speed scale, you need to enter a speed value as well.");
}
return Json(true);
}
My speed kendo control :
<div class="mb-5 col-md-6 idb_Incident_Speed">
#Html.LabelFor(model => model.Speed, htmlAttributes: new { #class = "control-label col-12" })
<div class="col-12">
<kendo-numerictextbox deferred="true" for="Speed"
format="#.##"
min="0"
name="Speed"
decimals="2"
placeholder="Enter Speed at time of Incident">
</kendo-numerictextbox>
#Html.ValidationMessageFor(model => model.Speed, "", new { #class = "text-danger" })
</div>
</div>
If I inspect the html of the form field I can see the properties are being set. But nothing happens:
What am I missing here?
Doesn't seem like this is supported out of the box. You have to write some custom jquery to get it to work:
#using(Html.BeginForm("FormPost","Home",FormMethod.Post,new {id="myForm"}))
{
<div class="mb-5 col-md-6 idb_Incident_Speed">
#Html.LabelFor(model => model.Speed, htmlAttributes: new { #class = "control-label col-12" })
<div class="col-12">
<kendo-numerictextbox deferred="true" for="Speed"
format="#.##"
min="0"
name="Speed"
decimals="2"
placeholder="Enter Speed at time of Incident">
</kendo-numerictextbox>
#Html.ValidationMessageFor(model => model.Speed, "", new { #class = "text-danger" })
</div>
</div>
#(Html.Kendo().Button()
.Name("btn")
.Content("Submit")
.HtmlAttributes(new {type="submit"})
)
}
#Html.Kendo().DeferredScripts()
<script>
$(document).ready( function () {
var validator = $("#myForm").kendoValidator({
rules: {
remote: function (input) {
if (input.val() == "" || !input.attr("data-val-remote-url")) {
return true;
}
if (input.attr("data-val-remote-recieved")) {
input.attr("data-val-remote-recieved", "");
return !(input.attr("data-val-remote"));
}
var url = input.attr("data-val-remote-url");
var postData = {};
postData[input.attr("data-val-remote-additionalfields").split(".")[1]] = input.val();
var validator = this;
var currentInput = input;
input.attr("data-val-remote-requested", true);
$.ajax({
url: url,
type: "POST",
data: JSON.stringify(postData),
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function (data) {
if (data == true) {
input.attr("data-val-remote", "");
}
else {
input.attr("data-val-remote", data);
}
input.attr("data-val-remote-recieved", true);
validator.validateInput(currentInput);
},
error: function () {
input.attr("data-val-remote-recieved", true);
validator.validateInput(currentInput);
}
});
return true;
}
},
messages: {
remote: function (input) {
return input.attr("data-val-remote");
}
}
}).getKendoValidator();
$("#btn").click(function(e){
e.preventDefault()
if(!validator.validate()){
//submit form
}
})
});
</script>
Special thanks to telerik support for the code sample.
I'm using ajax call to execute partial view controller action to print max batch number. Everything executes, but the value doesn't print in partial view. On selected dropdown list I'm calling ajax method to execute. Below is my code that i'm using.
Models.Batch.cs
[Required]
[StringLength(100)]
[DataType(DataType.Text)]
[Display(Name = "Batch Number")]
public string BatchNumber { get; set; }
BatchController.cs
public PartialViewResult GetBatchNumber(string CourseID)
{
Context.Batches contBatch = new Context.Batches();
Models.Batches b = new Models.Batches();
b.BatchNumber = contBatch.GetallBatchList().ToList().Where(p => p.CourseId == CourseID).Select(p => p.BatchNumber).Max().FirstOrDefault().ToString();
ViewBag.Message = b.BatchNumber;
return PartialView(b);
}
CreateBatch.cshtml
<div class="col-md-10">
#Html.DropDownListFor(m => m.CourseId, Model.Courses, new { id = "ddlCourse" })
<div id="partialDiv">
#{
Html.RenderPartial("GetBatchNumber", Model);
}
</div>
<script>
$("#ddlCourse").on('change', function () {
var selValue = $('#ddlCourse').val();
$.ajax({
type: "GET",
url: '/Batch/GetBatchNumber?CourseId=' + selValue,
dataType: "json",
data: "",
success: function (data) {
$("#partialDiv").html(data);
},
failure: function (data) {
alert('oops something went wrong');
}
});
});
</script>
</div>
GetBatchNumber.cshtml
#model WebApplication1.Models.Batches
<div class="form-group">
#Html.LabelFor(model => model.BatchNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.BatchNumber)
#Html.ValidationMessageFor(model => model.BatchNumber, "", new { #class = "text-danger" })
</div>
</div>
I'm having some trouble setting up the routing to a custom controller in Orchard.
I've created a View:
#model dynamic
#{
Script.Require("jQuery");
}
#using (Html.BeginForm("Send", "Email", FormMethod.Post, new { id = "contactUsForm" }))
{
<fieldset>
<legend>Contact Us</legend>
<div class="editor-label">Name:</div>
<div class="editor-field">
#Html.TextBox("Name", "", new {style = "width: 200px"})
</div>
<div class="editor-label">Email Address:</div>
<div class="editor-field">
#Html.TextBox("Email", "", new {style = "width: 200px"})
</div>
<div class="editor-label">Telephone Number:</div>
<div class="editor-field">
#Html.TextBox("Telephone", "", new {style = "width: 200px"})
</div>
<div class="editor-label">Message:</div>
<div class="editor-field">
#Html.TextArea("Message", "", new {style = "width: 200px"})
</div>
<br/>
<input id="ContactUsSend" type="button" value="Submit" />
</fieldset>
}
#using (Script.Foot()) {
<script>
$(function() {
$('#ContactUsSend').click(function () {
alert('#Url.Action("Send", "Email")');
var formData = $("#contactUsForm").serializeArray();
$.ajax({
type: "POST",
url: '#Url.Action("Send", "Email")',
data: formData,
dataType: "json",
success: function (data) {
alert(data);
}
});
});
});
</script>
}
With a Controller:
public class EmailController : Controller
{
[HttpPost]
public ActionResult Send()
{
var orchardServices = DependencyResolver.Current.GetService<IOrchardServices>();
var messageHandler = DependencyResolver.Current.GetService<IMessageManager>();
var svc = new ContactUsService(orchardServices, messageHandler);
svc.DoSomething();
return new EmptyResult();
}
}
And setup the route:
public class Routes : IRouteProvider {
public void GetRoutes(ICollection<RouteDescriptor> routes) {
foreach (var routeDescriptor in GetRoutes()) {
routes.Add(routeDescriptor);
}
}
public IEnumerable<RouteDescriptor> GetRoutes() {
return new[] {
new RouteDescriptor {
Priority = 15,
Route = new Route(
"ContactUsWidget",
new RouteValueDictionary {
{"area", "ContactUsWidget"},
{"controller", "Email"},
{"action", "Send"}
},
new RouteValueDictionary(),
new RouteValueDictionary {
{"area", "ContactUsWidget"}
},
new MvcRouteHandler())
}
};
}
}
But when I click the submit button, it tries to post to
OrchardLocal/Contents/Email/Send
and obviously fails. Can anyone point me in the direction of what I'm doing wrong?
Try this:
#using (Html.BeginForm("Send", "Email", new { area = "Your.Module" }, FormMethod.Post, new { id = "contactUsForm" }))
Adding the area is like an extra clause that ensures only your module is searched for a matching controller/action method pair.
I want to transfer model data from one View to another View (in a dialog) using Ajax.Actionlink were i am getting null values on Post Action
This is my View
#using (Ajax.BeginForm("", new AjaxOptions { }))
{
for (int i = 0; i < Model.city.Count; i++)
{
<div class="editor">
<p>
#Html.CheckBoxFor(model => model.city[i].IsSelected, new { id = "check-box-1" })
#Html.HiddenFor(model => model.city[i].Id)
#Ajax.ActionLink(Model.city[i].Name, "PopUp", "Home",
new
{
#class = "openDialog",
data_dialog_id = "emailDialog",
data_dialog_title = "Cities List",
},
new AjaxOptions
{
HttpMethod = "POST"
})
#Html.HiddenFor(model => model.city[i].Name)
</p>
</div>
}
}
On using Ajax.Actionlink i am creating a dialog using ajax scripting
My controller class for this View is
public ActionResult Data()
{
var cities = new City[] {
new City { Id = 1, Name = "Mexico" ,IsSelected=true},
new City { Id = 2, Name = "NewJersey",IsSelected=true },
new City { Id = 3, Name = "Washington" },
new City { Id = 4, Name = "IIlinois" },
new City { Id = 5, Name = "Iton" ,IsSelected=true}
};
var model = new Citylist { city = cities.ToList() };
//this.Session["citylist"] = model;
return PartialView(model);
}
another View for displaying Post action data is
#model AjaxFormApp.Models.Citylist
#{
ViewBag.Title = "PopUp";
}
<h2>
PopUp</h2>
<script type="text/javascript">
$(function () {
$('form').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
var checkedAtLeastOne = false;
$('input[id="check-box-2"]').each(function () {
if ($(this).is(":checked")) {
checkedAtLeastOne = true;
// alert(checkedAtLeastOne);
}
});
if (checkedAtLeastOne == true) {
// alert("Test");
$('#div1').show();
$(".dialog").dialog("close");
}
else {
// alert("NotSelected");
$('#div1').hide();
$('#popUp').html(result);
$('#popUp').dialog({
open: function () { $(".ui-dialog-titlebar-close").hide(); },
buttons: {
"OK": function () {
$(this).dialog("close");
}
}
});
}
}
});
return false;
});
});
</script>
<div style="display: none" id="div1">
<h4>
Your selected item is:
</h4>
</div>
#using (Ajax.BeginForm(new AjaxOptions { }))
{
for (int i = 0; i < Model.city.Count; i++)
{
<div class="editor">
<p>
#Html.CheckBoxFor(model => model.city[i].IsSelected,new { id = "check-box-2" })
#Html.HiddenFor(model => model.city[i].Id)
#Html.LabelFor(model => model.city[i].Name, Model.city[i].Name)
#Html.HiddenFor(model => model.city[i].Name)
</p>
</div>
}
<input type="submit" value="OK" id="opener" />
}
#*PopUp for Alert if atleast one checkbox is not checked*#
<div id="popUp">
</div>
and my post controller action result class is
[HttpPost]
public ActionResult PopUp(Citylist model)
{
if (Request.IsAjaxRequest())
{
//var model= this.Session["citylist"];
return PartialView("PopUp",model);
}
return View();
}
My model class is
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class Citylist
{
public IList<City> city { get; set; }
}
You are calling Popup action from actionlink. Instead you should place submit button out of for loop. And give your form right action parameters
I am new to MVC3 and trying to build a simple Invoicing app. The problem with my code is that the Ajax Post is failing and I cant find out why. Stepped through the JQuery code and it seems fine but by the time the POST hits the controller, the Model.IsValid is false. The problem seems to be with the child records. The invoice Master record is being saved to the DB but the InvoiceRow isnt. The problem lies in the SaveInvoice() function.
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>
You need to examine the Model and extract the errors. With those in hand you can begin fixing the problems that are causing the model binder to fail.
Here's an extension method I use to dump invalid model errors to the output console
http://pastebin.com/S0gM3vqg