Posting model data from one View to another in mvc3 using ajx - asp.net-mvc-3

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

Related

Remote dataannotation not triggering in front-end with kendo controls

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.

Ajax call always going in error part

I have demo in mvc where I want to fetch user details based on dropdown, i am using ajax for selectedindex changed event of dropdown to show userdetails in partial view, but ajax call is always going in error part..
Controller :-
public ActionResult Index()
{
var usermodel = new UserModel();
usermodel.listuser = GetUserData();
usermodel.UserId = usermodel.listuser.First().UserId;
usermodel.UserName = usermodel.listuser.First().UserName;
usermodel.UserSalary = usermodel.listuser.First().UserSalary;
return View(usermodel);
}
public PartialViewResult GetUserRecord(int UserId)
{
var userModel = new UserModel();
userModel.listuser = GetUserData();
var user = userModel.listuser.Where(e => e.UserId == UserId).FirstOrDefault();
userModel.UserId = user.UserId;
userModel.UserName = user.UserName;
userModel.UserSalary = user.UserSalary;
return PartialView("_UserTestPartial.cshtml", userModel);
}
private List<UserModel> GetUserData()
{
var listuser = new List<UserModel>();
var user1 = new UserModel();
user1.UserId = 1;
user1.UserName = "Abcd";
user1.UserSalary = 25000;
var user2 = new UserModel();
user2.UserId = 2;
user2.UserName = "bcde";
user2.UserSalary = 35000;
var user3 = new UserModel();
user3.UserId = 1;
user3.UserName = "cdef";
user3.UserSalary = 45000;
listuser.Add(user1);
listuser.Add(user2);
listuser.Add(user3);
return listuser;
}
Model:-
public class UserModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public double UserSalary { get; set; }
public List<UserModel> listuser { get; set; }
public IEnumerable < SelectListItem > UserListItems
{
get
{
return new SelectList(listuser, "UserId", "UserName");
}
}
}
Index View:-
#Html.DropDownListFor(m => m.UserId, Model.UserListItems, "---Select User--- ", new { Class = "ddlStyle", id = "ddlUser" })
<div id="partialDiv">
#Html.Partial("_UserTestPartial")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#ddlUser").on("change", function () {
$.ajax(
{
url: '/User/GetUserRecord?UserId=' + $(this).attr("value"),
type: 'GET',
data: " ",
contentType: 'application/json; charset=utf-8',
success: function (data) {
$("#partialDiv").html(data);
},
error: function () {
alert("error");
}
});
});
});
</script>
Partial View:-
#model Dropdowndemo.Models.UserModel
<fieldset>
<legend>UserModel</legend>
<div class="display-label">
<strong> #Html.DisplayNameFor(model => model.UserId) </strong>
</div>
<div class="display-field">
#Html.DisplayFor(model => model.UserId)
</div>
<div class="display-label">
<strong> #Html.DisplayNameFor(model => model.UserName) </strong>
</div>
<div class="display-field">
#Html.DisplayFor(model => model.UserName)
</div>
<div class="display-label">
<strong> #Html.DisplayNameFor(model => model.UserSalary) </strong>
</div>
<div class="display-field">
#Html.DisplayFor(model => model.UserSalary)
</div>
</fieldset>
Please remove the data: " ", attribute from ajax, if you're not passing any in it.
In the Index remove
#Html.Partial("_UserTestPartial")
This will throw error since you are not passing any model to the partial view in this way.
As you were binding the partial view via ajax call to #partialDiv it will work fine

Many to Many Relation Popup

basically from embedded field and new to MVC/ASP.net, learning.
I have 2 entities with Many to Many relation.
It is working fine i am able to assign relation bet
Heading
ween them using checkbox.
I want to implement the following:
On Create page of Entity 1, Relative Entity 2 list is shown in table with Link and Unlink buttons.
Find below Image:
Link button will open up the popup which will show Entity 2 listing which is not there in the relation with the Entity 1.
User will select the required Entity 2 using checkbox and press 'Submit button.
On pressing Submit button, the selected Entity 2 objects are added to the **Entity 2 ** table in the Create view and popup closes.
On Saving create view will save everything with relation.
I hope I'm not asking too much... Not able to judge.
Thanks in advance.
Already Working:
1) I am able to open the model using bootstrap modal popup approach and pass the Entity 2 list to it.
2.) I am able to display the list in table.
To achieve:
1) Populate Entity 2 list in popup view with objects which are not in the Entity 2 table in the main view.
2) Have Checkbox in Popup table for selection.
3) Get the selected Entity 2 row details to main view without posting to controller.
4) Update Entity 2 table in the main view with the selected rows.
5) Save to table when save button is pressed..
Entity 1:
public partial class JobPost
{
public JobPost()
{
this.JobTags = new HashSet<JobTag>();
}
public int JobPostId { get; set; }
public string Title { get; set; }
public virtual ICollection<JobTag> JobTags { get; set; }
}
Entity 2:
public partial class JobTag
{
public JobTag()
{
this.JobPosts = new HashSet<JobPost>();
}
public int JobTagId { get; set; }
public string Tag { get; set; }
public virtual ICollection<JobPost> JobPosts { get; set; }
}
public class TempJobTag
{
public int JobTagId { get; set; }
public string Tag { get; set; }
public bool isSelected { get; set; }
}
View Model:
public class JobPostViewModel
{
public JobPost JobPost { get; set; }
public IEnumerable<SelectListItem> AllJobTags { get; set; }
private List<int> _selectedJobTags;
public List<int> SelectedJobTags
{
get
{
if (_selectedJobTags == null)
{
_selectedJobTags = JobPost.JobTags.Select(m => m.JobTagId).ToList();
}
return _selectedJobTags;
}
set { _selectedJobTags = value; }
}
}
Entity 1 Controller:
// GET: JobPosts/Create
public ActionResult Create()
{
var jobPostViewModel = new JobPostViewModel
{
JobPost = new JobPost(),
};
if (jobPostViewModel.JobPost == null)
return HttpNotFound();
var allJobTagsList = db.JobTags.ToList();
jobPostViewModel.AllJobTags = allJobTagsList.Select(o => new SelectListItem
{
Text = o.Tag,
Value = o.JobTagId.ToString()
});
return View(jobPostViewModel);
}
// POST: JobPosts/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(JobPostViewModel jobpostView)
{
if (ModelState.IsValid)
{
var newJobTags = db.JobTags.Where(
m => jobpostView.SelectedJobTags.Contains(m.JobTagId)).ToList();
var updatedJobTags = new HashSet<int>(jobpostView.SelectedJobTags);
foreach (JobTag jobTag in db.JobTags)
{
if (!updatedJobTags.Contains(jobTag.JobTagId))
{
jobpostView.JobPost.JobTags.Remove(jobTag);
}
else
{
jobpostView.JobPost.JobTags.Add((jobTag));
}
}
db.JobPosts.Add(jobpostView.JobPost);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(jobpostView);
}
public ActionResult ViewJobPostTagPopUp()
{
var allJobTagsList = db.JobTags.ToList();
foreach (JobTag jobTag in db.JobTags)
{
if (jobTag.JobTagId == 1)
{
allJobTagsList.Remove(jobTag);
}
}
List<TempJobTag> tmpJobTags = new List<TempJobTag>();
foreach (JobTag jobTag in db.JobTags)
{
TempJobTag tmpJT = new TempJobTag();
tmpJT.Tag = jobTag.Tag;
tmpJT.JobTagId = jobTag.JobTagId;
tmpJobTags.Add(tmpJT);
}
return PartialView("JobTagIndex", tmpJobTags);
}
[HttpPost]
//[ValidateAntiForgeryToken]
public JsonResult ViewJobPostTagPopUp(List<TempJobTag> data)
{
if (ModelState.IsValid)
{
}
return Json(new { success = true, message = "Some message" });
}
Main View:
#model MVCApp20.ViewModels.JobPostViewModel
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>JobPost</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.JobPost.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.JobPost.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.JobPost.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AllJobTags, "JobTag", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.ListBoxFor(m => m.SelectedJobTags, Model.AllJobTags)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("+", "ViewJobPostTagPopUp", "JobPosts",
null, new { #class = "modal-link btn btn-success" })
</div>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
<script src="~/Scripts/jquery-2.1.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript">
</script>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Partial Popup View:
#model IEnumerable<MVCApp20.Models.TempJobTag>
#{
ViewBag.Title = "Index";
//Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Tags</h2>
#using (Html.BeginForm())
{
<table id="datatable" class="table">
<tr>
<th>
<input type="checkbox" id="checkAll" />
</th>
<th>
#Html.DisplayNameFor(model => model.Tag)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#*#Html.EditorFor(modelItem => item.isSelected)*#
<input type="checkbox" class="checkBox"
value="#item.isSelected" />
</td>
<td>
#Html.DisplayFor(modelItem => item.Tag)
</td>
</tr>
}
</table>
#*<div>
#Html.ActionLink("Done", "ViewJobPostTagPopUp", "JobPosts",
null, new { #class = "modal-link btn btn-primary" })
</div>*#
<div>
<button type="submit" id="btnSubmit" class=" btn btn-primary">Submit</button>
</div>
}
<script>
$(document).ready(function () {
$("#checkAll").click(function () {
$(".checkBox").prop('checked',
$(this).prop('checked'));
});
});
$(function () {
$('#btnSubmit').click(function () {
var sdata = new Array();
sdata = getSelectedIDs();
var postData = {};
postData[values] = sdata;
$.ajax({
url: '#Url.Action("ViewJobPostTagPopUp")',
type: "POST",
type: this.method,
//data: $(this).serialize(),
data: JSON.stringify(product),
success: function (result) {
alert("success");
},
fail: function (result) {
alert("fail");
}
});
//alert("hiding");
//$('#modal-container').modal('hide');
});
});
function getSelectedIDs() {
var selectedIDs = new Array();
var i = 0;
$('input:checkbox.checkBox').each(function () {
if ($(this).prop('checked')) {
selectedIDs.push($(this).val());
i++;
alert("got" + i);
}
});
return selectedIDs;
}
</script>

Routing a custom controller in Orchard CMS

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.

Asp.Net MVC 3 (Razor, Json, Ajax) Master Detail - detail save failing

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

Resources