Use ajax in asp.net mvc 5 in a tab - ajax

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 ))
{
}

Related

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

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!!

MVC validation focusing the date time control on validation fail

I am having my view as follows
#using (Html.BeginForm("Apply", "Leave", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group">
Leave Type
#Html.DropDownListFor(m => m.LeaveTypeId, Model.LeaveType, "Choose...", new { #class = "form-control", #tabindex = "1" })
#Html.ValidationMessageFor(m => m.LeaveTypeId, "", new { #class = "label-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="form-group">
From Date
#Html.TextBoxFor(m => m.FromDate, new { #class = "form-control", #tabindex = "2" })
#Html.ValidationMessageFor(m => m.FromDate, "", new { #class = "label-danger" })
</div>
</div>
}
When I click on apply button it is auto focusing the next control as my tab index was set. So is there any way to focus but not display the datetime control

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.

Resources