ASP.NET Core MVC Ajax post on success returning html page and then in the page shows only a json? - ajax

Basically I call the SendInvoince method from the controller and an invoice is sent!
The problem is with the ajax post upon success the data is the html page instead of the json returned from the controller method, poping up the swal error and after 1 sec it refreshes the page showing a page with only the json returned by the controller!???? Why? What is happening?
This is my controller:
[HttpPost]
public IActionResult SendInvoice(Document document)
{
bool success = false;
string errorMessage = null;
string session = GetSession();
document.Docktype = "4";
try
{
document.Id = InsertDocumentHeader(document, session);
InsertDocumentLine(document, session);
document.Id = CloseDocument(document, session);
Client client = GetClient(session, document.NIF);
SendDocumentPDF2Email(document, session, client.Email);
success = true;
}
catch (Exception e)
{
errorMessage = e.Message;
}
return Json(new { success, Error = errorMessage });
}
This is my view:
#{
ViewData["Title"] = "Home Page";
}
#model WebApplication2.Controllers.HomeController.HomeModel
<style>
.required:after {
content: " *";
color: red;
}
.control-label {
margin-left: 2%;
}
</style>
<div>
<div id="AddClientModal" class="modal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Add Client</h4>
<button type="button" class="close" data-dismiss="modal">X</button>
</div>
<br />
<form action="#Url.Action("CreateClient", "Home")" method="post" id="addClientForm">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<b style="color:red; margin-left: 2%; ">* </b>Required field
<br />
<div class="form-group">
#Html.LabelFor(model => model.Client.NIF,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.NIF,
new { htmlAttributes = new { #class = "form-control", #id = "clientNIF" } })
#Html.ValidationMessageFor(model => model.Client.NIF,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.Name,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.Name,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.Name,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.Address,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.Address,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.Address,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.Locality,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.Locality,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.Locality,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.PostalCode,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.PostalCode,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.PostalCode,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.Email,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.Email,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.Email,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.Fax,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.Fax,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.Fax,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.Phone,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.Phone,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.Phone,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client.Obs,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Client.Obs,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client.Obs,
"", new { #class = "text-danger" })
</div>
</div>
</form>
<div class="modal-footer">
<button id="btnAddClientFormSubmit" class="btn btn-success" form="addClientForm" type="button">Create</button>
<button id="btnAddClientFormCancel" class="btn btn-danger" type="button">Cancel</button>
</div>
</div>
</div>
</div>
<div>
<div id="SendInvoiceModal" class="modal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Send Invoice</h4>
<button type="button" class="close" data-dismiss="modal">X</button>
</div>
<br />
<form action="#Url.Action("SendInvoice", "Home")" method="post" id="SendInvoiceForm">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<b style="color:red; margin-left: 2%; ">* </b>Required field
<br />
<div class="form-group">
#Html.LabelFor(model => model.Client,
htmlAttributes: new { #class = "control-label required" })
<div class="col-md-8">
#Html.DropDownListFor(model => model.Document.NIF,
Model.Clients.Select(x => new SelectListItem { Text = x.Name, Value = x.NIF }), null,
new { htmlAttributes = new { #class = "form-control", #id = "optClientNIF" } })
#Html.ValidationMessageFor(model => model.Document.NIF,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Document.Obs,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Document.Obs,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Document.Obs,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Document.DocRef,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Document.DocRef,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Document.DocRef,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Document.Qt,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Document.Qt,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Document.Qt,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Document.Price,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Document.Price,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Document.Price,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Document.Tax,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Document.Tax,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Document.Tax,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Document.ProdDesc,
htmlAttributes: new { #class = "control-label" })
<div class="col-md-8">
#Html.EditorFor(model => model.Document.ProdDesc,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Document.ProdDesc,
"", new { #class = "text-danger" })
</div>
</div>
</form>
<div class="modal-footer">
<button id="btnSendInvoiceFormSubmit" class="btn btn-success" form="SendInvoiceForm" type="submit">Create</button>
<button id="btnSendInvoiceFormCancel" class="btn btn-danger" type="button">Cancel</button>
</div>
</div>
</div>
</div>
<div>
<button id="AddClientModalBtn" class="btn btn-primary" type="button">Insert Client</button>
<button id="SendInvoiceModalBtn" class="btn btn-primary" type="button">Send Invoice</button>
</div>
<div class="card shadow mb-4" style="margin-top: 3%;">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Clients</h6>
</div>
<div class="card-body" style="margin-bottom: 1rem">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.Client.NIF)</th>
<th>#Html.DisplayNameFor(model => model.Client.Name)</th>
<th>#Html.DisplayNameFor(model => model.Client.Address)</th>
<th>#Html.DisplayNameFor(model => model.Client.Locality)</th>
<th>#Html.DisplayNameFor(model => model.Client.PostalCode)</th>
<th>#Html.DisplayNameFor(model => model.Client.Email)</th>
<th>#Html.DisplayNameFor(model => model.Client.Fax)</th>
<th>#Html.DisplayNameFor(model => model.Client.Phone)</th>
<th>#Html.DisplayNameFor(model => model.Client.Obs)</th>
</tr>
</thead>
<tfoot>
<tr>
<th>#Html.DisplayNameFor(model => model.Client.NIF)</th>
<th>#Html.DisplayNameFor(model => model.Client.Name)</th>
<th>#Html.DisplayNameFor(model => model.Client.Address)</th>
<th>#Html.DisplayNameFor(model => model.Client.Locality)</th>
<th>#Html.DisplayNameFor(model => model.Client.PostalCode)</th>
<th>#Html.DisplayNameFor(model => model.Client.Email)</th>
<th>#Html.DisplayNameFor(model => model.Client.Fax)</th>
<th>#Html.DisplayNameFor(model => model.Client.Phone)</th>
<th>#Html.DisplayNameFor(model => model.Client.Obs)</th>
</tr>
</tfoot>
<tbody>
#foreach (Client row in Model.Clients)
{
<tr id="#row.NIF">
<td>#row.NIF</td>
<td>#row.Name)</td>
<td>#row.Address</td>
<td>#row.Locality</td>
<td>#row.PostalCode</td>
<td>#row.Email</td>
<td>#row.Fax</td>
<td>#row.Phone</td>
<td>#row.Obs</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="~/lib/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="~/lib/limonte-sweetalert2/sweetalert2.min.js"></script>
#*<script type="text/javascript" src="~/lib/datatables/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="~/lib/datatables/js/dataTables.bootstrap4.js"></script>*#
#{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
<script>
function CheckNIF(NIF) {
var isValid = false;
const arrayNIF = Array.from(String(NIF), Number);
var sum = 0;
var multi = 9;
for (var i = 0; i < arrayNIF.length - 1; i++) {
sum += arrayNIF[i] * multi;
multi--;
}
var result = sum % 11;
if (result == 0 || result == 1) {
result = 0;
}
else {
result = 11 - result;
}
if (result == arrayNIF[8]) {
isValid = true;
}
else {
isValid = false;
}
return isValid;
}
$(document).ready(function () {
$('#AddClientModalBtn').click(function () {
$("#AddClientModal").modal('show');
});
$('#btnAddClientFormSubmit').click(function () {
var NIF = document.getElementById('clientNIF').value
if (CheckNIF(NIF)) {
$("#addClientForm").submit();
}
else {
console.log("Error");
swal.fire({
position: 'top',
type: 'error',
title: 'Invalid NIF',
text: 'Please enter a valid NIF',
allowOutsideClick: false,
});
}
});
$('#btnAddClientFormCancel').click(function () {
$("#AddClientModal").modal('hide');
$("#addClientForm").trigger('reset');
});
$('#SendInvoiceModalBtn').click(function () {
$("#SendInvoiceModal").modal('show');
});
$('#btnSendInvoiceFormCancel').click(function () {
$("#SendInvoiceModal").modal('hide');
$("#SendInvoiceForm").trigger('reset');
});
$(function () {
$('#addClientForm').submit(function () {
$.ajax({
url: this.url,
type: this.method,
data: $(this).serialize(),
success: function (data) {
if (data.success) {
Swal.fire({
position: 'top-end',
type: 'success',
title: 'Client added.',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
});
console.log("Success");
}
else {
Swal.fire({
type: 'error',
text: 'Error adding client. If the problem persists, please contact the support.',
allowOutsideClick: false,
});
console.log("Server Error");
}
},
error: function () {
console.log("Request failed");
}
});
});
});
$(function () {
$('#SendInvoiceForm').submit(function (event) {
event.preventDefault();
$.ajax({
url: this.url,
type: this.method,
data: $(this).serialize(),
success: function (data) {
console.log("HELLO");
console.log(data);
console.log(data.length);
console.log(data.success);
if (data.success) {
Swal.fire({
position: 'top-end',
type: 'success',
title: 'Invoice sent.',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
});
console.log("Success");
}
else {
Swal.fire({
type: 'error',
text: 'Error sending invoice. If the problem persists, please contact the support.',
allowOutsideClick: false,
});
console.log("Server Error");
}
},
error: function () {
console.log("Request failed");
}
});
});
});
});
</script>
this are the console.logs (console.log(data), console.log(data.lenght), console.log(data.success)):
And this is the page after the ajax post:
Best regards!!

After some time spent with this I found out that using: this.url for ajax url was the problem!!!!
before:
$(function () {
$('#SendInvoiceForm').submit(function (event) {
event.preventDefault();
$.ajax({
url: this.url,
type: this.method,
data: $(this).serialize(),
SndInvoiceForm as the action:
<form action="#Url.Action("SendInvoice", "Home")" method="post" id="SendInvoiceForm">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<b style="color:red; margin-left: 2%; ">* </b>Required field
Don't know why it doesn't work??
After:
$(function () {
$('#SendInvoiceForm').submit(function (event) {
event.preventDefault();
$.ajax({
url: '#Url.Action("SendInvoice", "Home")',
type: this.method,
data: $(this).serialize(),
Now Works!!!!
If someone knows why, please let me know!!

Related

Use ajax in asp.net mvc 5 in a tab

I want to use ajax to update the content of a TAB and it doesn't work, when I press the buton submit i update all the page. I don't know how to solve it.
Thanks.
Controller PeticioUsuarisController:
// POST: PeticioUsuaris/_Demanar
// 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 _Demanar([Bind(Include = "Nom,PrimerCognom,SegonCognom")] PeticioUsuari peticioUsuari)
{
if (ModelState.IsValid)
{
peticioUsuari.IdUsuariFaPeticio = 1;
db.PeticioUsuari.Add(peticioUsuari);
db.SaveChanges();
return PartialView("_PeticioCorrecte");
}
return PartialView("_PeticioCorrecte");
}
View Index.cshtml:
#{
ViewBag.Title = "";
}
<!-- Tab Buttons -->
<ul id="tabstrip" class="nav nav-tabs" role="tablist">
<li class="active">Demanar</li>
<li>Acceptar</li>
</ul>
<!-- Tab Content Containers -->
<div class="tab-content">
<div class="tab-pane fade in active" id="_Demanar">#Html.Partial("_Demanar")</div>
<div class="tab-pane fade" id="_AcceptarPeticio"></div>
</div>
#section scripts {
<script>
$('#tabstrip a').click(function (e) {
e.preventDefault()
var tabID = $(this).attr("href").substr(1);
$(".tab-pane").each(function () {
console.log("clearing " + $(this).attr("id") + " tab");
$(this).empty();
});
//$("#" + tabID).load("/#ViewContext.RouteData.Values["controller"]/" + tabID)
$.ajax({
url: "/#ViewContext.RouteData.Values["controller"]/" + tabID,
cache: false,
type: "get",
dataType: "html",
success: function (result) {
$("#" + tabID).html(result);
}
})
$(this).tab('show')
});
</script>
}
View _Demanar:
#model Peticions.Models.PeticioUsuari
#{
AjaxOptions options = new AjaxOptions
{
HttpMethod = "Post",
UpdateTargetId = "content",
InsertionMode = InsertionMode.InsertAfter
};
}
#using (Ajax.BeginForm("_Demanar", "PeticioUsuaris", null, options))
{
#Html.AntiForgeryToken()
<div class="form-horizontal tabs">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Nom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Nom, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Nom, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PrimerCognom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PrimerCognom, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PrimerCognom, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SegonCognom, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SegonCognom, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SegonCognom, "", new { #class = "text-danger" })
</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 id="content"></div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
View _PeticioCorrecte:
#model Peticions.Models.PeticioUsuari
<div class="alert alert-success">
<a href="#Url.Action("Index", "PeticioUsuaris", new { id = UrlParameter.Optional })">
Petició enviada correctament! Clica aquí per a crear-ne un altre.
</a>
</div>
try this
#{
AjaxOptions options = new AjaxOptions
{
HttpMethod = "Post",
UpdateTargetId = "formContent"
};
}
#using (Ajax.BeginForm("_AcceptarPeticio", "PeticioUsuaris", null,options ))
{
}

I'm trying to send two parameters from view to controller but the second is always null

I'm trying to send two parameters (HttpPostedFileBase and the model) from the view to the Create method in the controller but the variable HttpPostedFile photos always gets null values.
Here is the Controller Code:
public async Task <ActionResult> Create([Bind(Include =
"Id,Name,Description")] Models.Environment environment, HttpPostedFileBase photos)
{
if (ModelState.IsValid)
{
if (photos!=null)
{
DataBlobImage dataBlobImage = new DataBlobImage();
environment.Logo = await
dataBlobImage.CreateImage("environment",
environment.Id.ToString(), photos);
}
//Creation date
environment.CreationDate = DateTime.Now;
//Get the creation user ID
environment.CreationUser = 1;
//By default when you create a user is active
environment.Active = true;
db.Environment.Add(environment);
await db.SaveChangesAsync();
return Json(new { success = true });
}
return View(environment);
}
View code:
#using (Html.BeginForm("ModalCreate", "Environment",
FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="modal-header create-window">
<button type="button" class="close"
data-dismiss="modal" aria- hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Crear nuevo Ambiente</h4>
</div>
<div class="modal-body">
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name,
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Description,
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Description,
new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<label for="file">Subir Imagen:</label>
<input id="photos" name="photos" type="file"
style="width: 100%;" />
</div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal">Cancelar</button>
<input class="btn btn-primary" type="submit" value="Crear" />
</div>
</div>
</div>
}
I think you don't need to pass an additional parameter for that. You can alway access it like below inside your action method:
HttpPostedFileBase file = Request.Files["NameOfYourFileUploadControl"];
Hope this will help.

Show only server side errors in validation summary

I have the following view:
#model MyProject.Models.RegisterViewModel
<div class="content">
<div class="wrapper">
<h2>E-Bill Saver Registration</h2>
<hr />
<div class="columns top-gap">
<div class="first cell width-6 dark-blue-headings">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#*#Html.ValidationSummary("", new { #class = "text-danger" })*#
<div class="form-horizontal">
<div class="form-group">
#Html.Label("Account Number", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.AccountNo, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.AccountNo, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("MPNumber", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.MPNumber, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.MPRN, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Email Address", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Confirm Email Address", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.ConfirmEmail, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.ConfirmEmail, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Password", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
#Html.Label("Confirm Password", htmlAttributes: new { #class = "control-label col-md-2 bold" })
<br />#Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { #class = "text-danger" })
<div class="col-md-10">
#Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { #class = "form-control input" } })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Register" class="opc_button" />
</div>
</div>
</div>
}
</div>
</div>
</div>
If there are validation errors on any of the fields then the error message is displayed below the label as expected and wanted. On my controller however I have some custom logic errors and I am adding them to the modelstate as follows:
else
{
//This email address is already assigned to a user
ModelState.AddModelError("Email Address : ", "Error! You must enter an email address that is unique to your account.");
return View(model);
}
If I uncomment the validationsummary on my page then it will display the custom server side error but it will also display the single validation errors which I want underneath the labels. Is there any way that I can set the validation summary to ignore the values that are being listed individually and only return server side validation errors?
The first string parameter of ModelState.AddModelError method is the key later used to bind the message to the model property.
If you want to display that error message next to email label, make first parameter of AddModelError match your property name:
ModelState.AddModelError("Email", "Error! Email already used...");

Model binding doesn't work when multiple instances of the same partial view are called dynamically with ajax.actionlink in MVC 5

I'm building a restaurant reservations system. When the user creates a reservation they can also decided what furniture will be used with the reservation. For this I created a partial view, so every time the user click on "add furniture" the partial view is loaded with ajax where the user can then specify what furniture and how many. They can add as many types of furniture as they want, meaning they can call the partial view as many times as they want. My problem comes in with the model binder, the model binder then have bind all those partial view instances to a list object of type "BistroReservations_ReservationsFurniture". Please help how to make the model binder work.
MainView (Please have a look at the bottom for the ajax.actionlink call "Add Furniture"
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>BistroReservations_Reservation</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.DateOfArrival, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateOfArrival, new { htmlAttributes = new { #class = "form-control datecontrol" } })
#Html.ValidationMessageFor(model => model.DateOfArrival, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_ShiftID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_ShiftID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_ShiftID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_GuestID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-6">
#Html.DropDownList("BistroReservations_GuestID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_GuestID, "", new { #class = "text-danger " })
#Ajax.ActionLink("Create a New Guest", "NewGuest", new AjaxOptions
{
HttpMethod = "GET",
UpdateTargetId = "NewGuest",
InsertionMode = InsertionMode.ReplaceWith,
})
</div>
</div>
<div id="NewGuest" class="form-group">
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.ArrivalTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ArrivalTime", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ArrivalTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LocationID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("LocationID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LocationID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_TypeOfSeatingID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_TypeOfSeatingID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_TypeOfSeatingID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TableNoID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("TableNoID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TableNoID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_StatusID, "BistroReservations_StatusID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_StatusID",null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_StatusID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Comment, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor( model => model.Comment, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comment, "", new { #class = "text-danger" })
#Ajax.ActionLink("Add Furniture", "Furniture", new AjaxOptions
{
HttpMethod = "GET",
UpdateTargetId = "Furniture",
InsertionMode = InsertionMode.InsertAfter
})
</div>
</div>
<div id="Furniture" class="form-group">
</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>
}
ActionResult returning the furniture partial view
public PartialViewResult Furniture()
{
ViewBag.BistroReservations_FurnitureID = new SelectList(db.BistroReservations_Furnitures, "BistroReservations_FurnitureID", "Description");
return PartialView("_Furniture");
}
Furniture partial view
#model CdvPortal.Models.BistroReservations.BistroReservations_ReservationFurniture
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.BistroReservations_FurnitureID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("BistroReservations_FurnitureID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BistroReservations_FurnitureID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group ">
#Html.LabelFor(model => model.Quantity, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Quantity, "", new { #class = "text-danger" })
</div>
</div>
</div>
Furniture Model
public class BistroReservations_ReservationFurniture
{
public int BistroReservations_ReservationFurnitureID { get; set; }
public int BistroReservations_ReservationID { get; set; }
public virtual BistroReservations_Reservation BistroReservations_Reservation { get; set; }
[Display(Name="Furniture Type")]
public int BistroReservations_FurnitureID { get; set; }
public virtual BistroReservations_Furniture BistroReservations_Furniture { get; set; }
public int Quantity { get; set; }
}
You #Ajax.ActionLink() method is returning views with duplicate id attributes (invalid html) and duplicate name attributes which are not prefixed with the correct property name and do not include indexers for binding to a collection. For example if the collection property is named FurnitureItems then the html needed for the Quantity property of typeof BistroReservations_ReservationFurniture would need to be
<input type="text" name="FurnitureItems[0].Quantity" ...>
<input type="text" name="FurnitureItems[1].Quantity" ...>
You can use the BeginCollectionItem helper to generate the controls, which might look like (assuming the property is named FurnitureItems)
#model CdvPortal.Models.BistroReservations.BistroReservations_ReservationFurniture
#using (Html.BeginCollectionItem("FurnitureItems"))
{
....
#Html.LabelFor(m => m.Quantity, ..)
#Html.EditorFor(m => m.Quantity, ..)
#Html.ValidationMessageFor(m => m.Quantity, ..)
}
This will generate the correct prefix and add include an indexer based on a guid which also allows you to delete items from the collection. This article explains the usage in more detail
A pure client side alternative is shown in this answer. This gives better performance, but is harder to maintain since changing anything in the BistroReservations_ReservationFurniture model means updating the client side template.

Multiple Partial view in Same page, opened one by one on request, returns the same model on submission

We are using MVC3 to develop an application. We need to create multiple entities - like customers - from the Main page. Same partial view is used to create this entity. These partial views are loaded on to Jquery model dialog(Different div tags are used) one by one on demand when clicked on a link/button. When we creates the first entity, it creates successfully and corresponding key is set to the main page. But when we try to create the second entity, the data passed to the controller is same as the first one and an exception is thrown because of unique key constraint. We tried by adding Modelstate.clear() , but no success. Now the surprise is that if we add the entities from bottom by clicking the button in reverse order (ie 3,2,1) it is getting created. Can anybody solve this?
Controller for partial View Loading and submission
public PartialViewResult _CustomerCreate()
{
CustomerViewModel customerviewmodel = new CustomerViewModel();
ModelState.Clear();
return PartialView(customerviewmodel);
}
public ActionResult _CustomerCreate(CustomerViewModel customerviewmodel)
{
CustomerBL customerBL = new CustomerBL();
ModelState.Clear();
if (ModelState.IsValid)
{
string path = Request.UrlReferrer.AbsolutePath;
}
int id = customerBL.SaveData(customerviewmodel);
string customer = Convert.ToString(customerviewmodel.FSTNAME + " " + customerviewmodel.MDLNAME + " " + customerviewmodel.LSTNAME);
return Json(new { Customerid = id, CustomerName = customer });
}
Sample script on the main page which loads partial View to Jquery Dialog
<script type="text/javascript">
$(function () {
$(".divnewnominee").dialog({
autoOpen: false, width: 800, height: 590, modal: true,
buttons: {
"Save": function () {
if ($("#CustomerFormID").validate().form()) {
$.post("/Customer/_CustomerCreate",
$("#CustomerFormID").serialize(),
function (data) {
$("#NOMINAME").val(data.CustomerName);
$("#NOMINEE").val(data.Customerid);
$(".divnewnominee").dialog("close");
});
}
},
Cancel: function () { $(this).dialog("close"); }
}
});
$(".newnominee").click(function () {
$(".divnewnominee").html("")
.dialog("option", "title", "New Customer")
.load("/Customer/_CustomerCreate", function () { $(".divnewnominee").dialog("open"); });
});
});
<script type="text/javascript">
$(function () {
$(".divfamily").dialog({
autoOpen: false, width: 800, height: 590, modal: true,
buttons: {
"Save": function () {
if ($("#CustomerFormID").validate().form()) {
$.post("/Customer/_CustomerCreate",
$("#CustomerFormID").serialize(),
function (data) {
$("#DEPOSITCUST").val(data.CustomerName);
$("#DEPOSITBY").val(data.Customerid);
$(".divfamily").dialog("close");
});
}
},
Cancel: function () { $(this).dialog("close"); }
}
});
$(".newfamily").click(function () {
$(".divfamily").html("")
.dialog("option", "title", "New Customer")
.load("/Customer/_CustomerCreate", function () { $(".divfamily").dialog("open"); });
});
});
Partial view which is loaded into the divs
#model ccs.Models.ViewModels.CustomerViewModel
#{
ViewBag.Title = "Create";
}
<h2>Customer</h2>
<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>
<script src="../../Scripts/ccsjs/ChooseFromList.js" type="text/javascript"> </script>
<script type="text/javascript">
$(function () {
$("#dialog").dialog({
autoOpen: false, width: 800, height: 500, modal: true,
buttons: {
"Save": function () {
if ($("#AddressLookup").validate().form()) {
$.post("/Customer/AddressLookupCreate",
$("#AddressLookup").serialize(),
function (data) {
$("#CustAddress").val(data.address);
$("#AddrID").val(data.Adressid);
$("#dialog").dialog("close");
});
}
},
Cancel: function () { $(this).dialog("close"); }
}
});
$(".Address").click(function () {
$("#dialog").html("")
.dialog("option", "title", "Address")
.load("/Customer/_AddressLookupCreate", function () { $("#dialog").dialog("open"); });
});
});
<script type="text/javascript" >
$(function () {
$("#addr").dialog({
autoOpen: false, width: 800, height: 550, modal: true,
buttons: {
"Add": function () {
if ($("#AddressLookupList").validate().form()) {
$.post("/Customer/_AddressLookupList",
$("#AddressLookupList").serialize(),
function (data) {
$("#CustAddress").val(data.address);
$("#AddrID").val(data.Adressid);
$("#addr").dialog("close");
});
}
},
Cancel: function () { $(this).dialog("close"); }
}
});
$(".searchaddr").click(function () {
$("#addr").html("")
.dialog("option", "title", "Address List")
.load("/Customer/_AddressLookupList", function () { $("#addr").dialog("open"); });
});
});
<script type="text/javascript">
$(function () {
$("#divcust").dialog({
autoOpen: false, width: 250, height: 500, modal: true
});
$("#custbtn").click(function () {
$("#divcust").html("")
.dialog("option", "title", "Customer List")
.load("/Customer/_CustomerList", function () { $("#divcust").dialog("open"); });
});
});
#using (Html.BeginForm("_CustomerCreate", "Customer", FormMethod.Post, new { id="CustomerFormID" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Create</legend>
<div style="float:left; width:100%;">
<div class="row-style">
<div class="labels">
#Html.Label("Customer Code")
</div>
<div id="Cust" class="fields">
#Html.TextBoxFor(model => model.CUSTCODE)
<div>#Html.ValidationMessageFor(model => model.CUSTCODE)</div>
</div>
<div class="labels">
#Html.Label("First Name")
</div>
<div class="fields">
#Html.EditorFor(model => model.FSTNAME)
<div> #Html.ValidationMessageFor(model => model.FSTNAME)</div>
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Middle Name")
</div>
<div class="fields">
#Html.EditorFor(model => model.MDLNAME)
#Html.ValidationMessageFor(model => model.MDLNAME)
</div>
<div class="labels">
#Html.Label("Last Name")
</div>
<div class="fields">
#Html.EditorFor(model => model.LSTNAME)
#Html.ValidationMessageFor(model => model.LSTNAME)
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Date of Birth")
</div>
<div class="fields">
#Html.TextBoxFor(model => model.DOB, new { #class = "datePicker", id = "DOB", style = "width:170px;" })
<div> #Html.ValidationMessageFor(model => model.DOB)</div>
</div>
<div class="labels">
#Html.Label("Gender")
</div>
<div class="fields">
#Html.DropDownListFor(model => model.Gender, new SelectList(Model.Gendr, "Key", "Value", " "), new { style = "width:205px;" })
#Html.ValidationMessageFor(model => model.Gender)
</div>
</div>
<div >
<div class="labels">
#Html.Label("Address ")
</div>
<div class="fields">
#Html.TextAreaFor(model => model.ADDRESS, new { #name = "ADDRESS", #readonly = "readonly", style = "width:170px;height:50px;" ,id="CustAddress"})
<img src="../../Content/themes/base/ccsimages/Search-icon.png" class="searchaddr" alt="Account Code" />
<img src="../../Content/themes/base/ccsimages/New.jpg" alt="Account Code" class="Address" width="16Px" height="16Px"/>
#* #Html.ActionLink("New Address", "AddressCreate")*#
#Html.ValidationMessageFor(model => model.ADDRESS)
</div>
<div class="labels">
#Html.Label("Photo ")
</div>
<div class="fields">
<p>
<input type="file" id="PhotoUpload" name="PhotoUpload" />
</p>
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Pan No")
</div>
<div class="fields">
#Html.EditorFor(model => model.ITPAN)
<div>#Html.ValidationMessageFor(model => model.ITPAN)</div>
</div>
<div class="labels">
#Html.Label("Tax Circle/Ward/District")
</div>
<div class="fields">
#Html.EditorFor(model => model.WARD)
#Html.ValidationMessageFor(model => model.WARD)
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Mobile No")
</div>
<div class="fields">
#Html.EditorFor(model => model.MOBILE)
#*#Html.CheckBoxFor(model => model.SNDSMS, new { #value = Model.MOBILE, #onchange = "check(value)" })*#
<div> #Html.ValidationMessageFor(model => model.MOBILE)</div>
</div>
<div class="labels">
#Html.Label("Email ")
</div>
<div class="fields">
#Html.EditorFor(model => model.EMAIL)
#*#Html.CheckBoxFor(model => model.SNDMSG)*#
<div> #Html.ValidationMessageFor(model => model.EMAIL)</div>
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Phone No ")
</div>
<div class="fields">
#Html.EditorFor(model => model.PHONE)
<div> #Html.ValidationMessageFor(model => model.PHONE)</div>
</div>
<div class="labels">
#Html.Label("Fax ")
</div>
<div class="fields">
#Html.EditorFor(model => model.FAX)
<div>#Html.ValidationMessageFor(model => model.FAX)</div>
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Family")
</div>
<div class="fields">
#Html.DropDownListFor(model => model.FMLY, new SelectList(Model.Famly, "Key", "Value", " "), new { style = "width:205px;" })
#Html.ValidationMessageFor(model => model.FMLY)
</div>
<div class="labels">
#Html.Label("Customer Type")
</div>
<div class="fields">
#Html.DropDownListFor(model => model.CUSTYPE, new SelectList(Model.CustTyp, "Key", "Value", " "), new { style = "width:205px;" })
#Html.ValidationMessageFor(model => model.CUSTYPE)
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Repledge")
</div>
<div class="fields">
#Html.DropDownListFor(model => model.REPLEDG, new SelectList(Model.Repldg, "Key", "Value", " "), new { style = "width:205px;" })
#Html.ValidationMessageFor(model => model.REPLEDG)
</div>
<div class="labels">
#Html.Label("ID Proof Type")
</div>
<div class="fields">
#Html.DropDownListFor(model => model.IDPRTYPE, new SelectList(Model.IdProoflist, "IDPRCODE", "IDPRNAME", " "), new { style = "width:205px;" })
#Html.ValidationMessageFor(model => model.IDPRTYPE)
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("ID Proof No")
</div>
<div class="fields">
#Html.EditorFor(model => model.IDPNO)
#Html.ValidationMessageFor(model => model.IDPNO)
</div>
<div class="labels">
#Html.Label("ID Proof ")
</div>
<div class="fields">
<p>
<input type="file" id="IDProofUpload" name="IDProofUpload" />
</p>
</div>
</div>
<div class="row-style">
<div class="labels">
#Html.Label("Father/Husband Name")
</div>
<div class="fields">
#Html.TextBoxFor(model => model.FNAME, new { #name = "FNAME", #class = "FNAME", style = "width:170px;" })
#*<img src="../../Content/themes/base/ccsimages/Search-icon.png" alt="Account Code" onclick="openCustPickerDialog(window, document.forms[0].FCUSTID,document.forms[0].FNAME, '/Customer/_CustomerLookupIndex/')" />*#
<img src="../../Content/themes/base/ccsimages/Search-icon.png" alt="Account Code" id="custbtn"/>
#Html.ValidationMessageFor(model => model.FNAME)
#Html.HiddenFor(model => model.FID)
</div>
</div>
</div>
#Html.HiddenFor(model => model.FCUSTID, new { #name = "FCUSTID",#class="FCUSTID", style = "width:130px;" })
<div class="fields">
#Html.HiddenFor(model => model.AVASRVCE)
</div>
<div class="fields">
#Html.HiddenFor(model => model.ADDRID, new { #name = "ADDRID", style = "width:130px;",id="AddrID" })
#Html.ValidationMessageFor(model => model.ADDRID)
</div>
#*<div id="NoteListBlock">#{Html.RenderPartial("_AddressLookupCreate");}</div>*#
<div id="dialog" title="Address Lookup"></div>
<div id="addr" title="Address"></div>
<div id="divcust" title="Customer List"></div>
<div class="row-style">
<div class="errorfield">
<div class="message"> #Html.ValidationMessageFor(model => model.CUSTCODE) #Html.ValidationMessageFor(model => model.FSTNAME) #Html.ValidationMessageFor(model => model.ADDRESS)</div>
</div>
</div>
</fieldset>
}
When First Div is submitted the data gets saved properly. When Second one submits the viewmodel retains the values from the first div
We solved our issue. We added on single line of code to the Java script which invoked the partial view. The code is given below
<script type="text/javascript">
$(function () {
$(".divnewnominee").dialog({
autoOpen: false, width: 800, height: 590, modal: true,
buttons: {
"Save": function () {
if ($("#CustomerFormID").validate().form()) {
$.post("/Customer/_CustomerCreate",
$("#CustomerFormID").serialize(),
function (data) {
***$(".divnewnominee").html(data);***
$("#NOMINAME").val(data.CustomerName);
$("#NOMINEE").val(data.Customerid);
$(".divnewnominee").dialog("close");
});
}
},
Cancel: function () { $(this).dialog("close"); }
}
});
$(".newnominee").click(function () {
$(".divnewnominee").html("")
.dialog("option", "title", "New Customer")
.load("/Customer/_CustomerCreate", function () { $(".divnewnominee").dialog("open"); });
});
});

Resources