how can fill a grid with kendo ui - asp.net-mvc

how can fill a grid with kendo.....
This is my controller
it`s work
public JsonResult listarporfecha([DataSourceRequest] DataSourceRequest request, string anio, string mes)
{
List<Reporte1Hist> reporte = new List<Reporte1Hist>();
DateTime fecha;
DateTime time;
short dia = 31;
short year = Convert.ToInt16(anio);
short m = Convert.ToInt16(mes);
// string date = anio + "-" + mes + "-" + dia;
DateTime fdate;
string MyString;
try
{
if (mes == null && anio == null)
{
fecha = DateTime.Now;
}
else
{
time = new DateTime(year, m, dia);
reporte = contexto.Reporte1Hist.Where(p => p.Fecha == time).ToList();
}
}
catch (Exception)
{
throw;
}
return Json(new[] { reporte }.ToDataSourceResult(request, ModelState));
}
and this is my jquery, it doesn't work,
var url = '#Url.Action("listarporfecha","Home")';
$.post(url, { anio: year, mes: month }, function (data) {
$("#Grid").kendoGrid({
dataSource: {
transport: {
read: {
type:"POST",
url: '#Url.Action("listarporfecha","Home")',
dataType: "json",
data:data
}
}
// schema: {
// data: "data"
//}
}
});
});

Related

Ajax Not Working on Edit Method

I have an ajax method for a cascading drop down list, similar to country - state drop down list. It works fine on Create method, but I can't get it to work on Edit method. I get this error on Edit:
POST http://localhost/Submissions/Edit/SomeAJAXMethod 500 (Internal Server Error)
There is an extra /Edit in the path that makes it not work. It works just fine on Create. I tried to add ~/. I get these errors on Create and Edit method:
POST http://localhost/Submissions/Edit/~/SomeAJAXMethod 404 (Not Found)
I tried to add ../. I get this error on Create, works fine on Edit:
POST http://localhost/SomeAJAXMethod 404 (Not Found)
How do I make it work on both Create and Edit?
Below is my controller.
//
// GET: /Submissions/Create
public ActionResult Create()
{
ViewBag.ActivityRejectCodeId = GetRejectCodesByActivity(0);
ViewBag.Activities = GetActivities();
ViewBag.Workstations = GetWorkstationsByActivity(0);
ViewBag.Platforms = GetPlatformsByWorkstation(0, 0);
ViewBag.Parts = GetPartsByPlatform(0, 0, 0);
ViewBag.StatusId = new SelectList(db.Status, "Id", "Name");
ViewBag.Technicians = GetTechnicians(0);
ViewBag.Shifts = GetShiftsByTechnician(0, 0);
ViewBag.WorkOrderId = new SelectList(db.WorkOrders, "Id", "WO");
return View();
}
//
// POST: /Submissions/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(WorkOrderSubmission workordersubmission)
{
var activityId = Int32.Parse(Request.Form["ActivityId"]);
var workstationId = Int32.Parse(Request.Form["WorkstationId"]);
var platformId = Int32.Parse(Request.Form["PlatformId"]);
var partId = Int32.Parse(Request.Form["PartId"]);
var techId = Int32.Parse(Request.Form["TechnicianId"]);
var shiftId = Int32.Parse(Request.Form["ShiftId"]);
if (ModelState.IsValid)
{
// Get the PlatformStageId from the combination of (ActivityId, WorkstationId, PlatformId, PartId)
var rs = (from ps in db.PlatformStages
join wa in db.WorkstationActivities on ps.WorkstationActivityId equals wa.Id
join pp in db.PlatformParts on ps.PlatformPartId equals pp.Id
where ps.WorkstationActivity.ActivityId == activityId
&& ps.WorkstationActivity.WorkstationId == workstationId
&& ps.PlatformPart.PlatformId == platformId
&& ps.PlatformPart.PartId == partId
select new {
ps.Id
}).FirstOrDefault();
workordersubmission.PlatformStageId = rs.Id;
// Get TechnicianShiftId from the combination of (TechnicianId, ShiftId)
rs = (from ts in db.TechnicianShifts
where ts.TechnicianId == techId
&& ts.ShiftId == shiftId
select new
{
ts.Id
}).FirstOrDefault();
workordersubmission.TechnicianShiftId = rs.Id;
workordersubmission.SubmissionDate = DateTime.Now;
db.WorkOrderSubmissions.Add(workordersubmission);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ActivityRejectCodeId = new SelectList(db.ActivityRejectCodes, "Id", "RejectCodeId", workordersubmission.ActivityRejectCodeId);
ViewBag.Activities = GetActivities(activityId);
ViewBag.Workstations = GetWorkstationsByActivity(activityId, workstationId);
ViewBag.Platforms = GetPlatformsByWorkstation(activityId, workstationId, platformId);
ViewBag.Parts = GetPartsByPlatform(activityId, workstationId, platformId, partId);
ViewBag.StatusId = new SelectList(db.Status, "Id", "Name", workordersubmission.StatusId);
ViewBag.Technicians = GetTechnicians(techId);
ViewBag.Shifts = GetShiftsByTechnician(techId, shiftId);
ViewBag.WorkOrderId = new SelectList(db.WorkOrders, "Id", "WO", workordersubmission.WorkOrderId);
return View(workordersubmission);
}
//
// GET: /Submissions/Edit/5
public ActionResult Edit(int id = 0)
{
WorkOrderSubmission workordersubmission = db.WorkOrderSubmissions.Find(id);
if (workordersubmission == null)
{
return HttpNotFound();
}
var platformStageId = workordersubmission.PlatformStageId;
var technicianShiftId = workordersubmission.TechnicianShiftId;
// Get ActivityId, WorkstationId, PlatformId, PartId from PlatformStageId
var rs = (from ps in db.PlatformStages
join wa in db.WorkstationActivities on ps.WorkstationActivityId equals wa.Id
join pp in db.PlatformParts on ps.PlatformPartId equals pp.Id
where ps.Id == platformStageId
select new
{
ActivityId = wa.ActivityId,
WorkstationId = wa.WorkstationId,
PlatformId = pp.PlatformId,
PartId = pp.PartId
})
.FirstOrDefault();
ViewBag.Activities = GetActivities(rs.ActivityId);
ViewBag.Workstations = GetWorkstationsByActivity(rs.ActivityId, rs.WorkstationId);
ViewBag.Platforms = GetPlatformsByWorkstation(rs.ActivityId, rs.WorkstationId, rs.PlatformId);
ViewBag.Parts = GetPartsByPlatform(rs.ActivityId, rs.WorkstationId, rs.PlatformId, rs.PartId);
// Get TechnicianId, ShiftId from TechnicianShiftId
var rs2 = (from ts in db.TechnicianShifts
where ts.Id == technicianShiftId
select new //TechnicianShift
{
TechnicianId = ts.TechnicianId,
ShiftId = ts.ShiftId
})
.FirstOrDefault();
ViewBag.Technicians = GetTechnicians(rs2.TechnicianId);
ViewBag.Shifts = GetShiftsByTechnician(rs2.TechnicianId, rs2.ShiftId);
ViewBag.ActivityRejectCodeId = new SelectList(db.ActivityRejectCodes, "Id", "RejectCodeId", workordersubmission.ActivityRejectCodeId);
ViewBag.StatusId = new SelectList(db.Status, "Id", "Name", workordersubmission.StatusId);
ViewBag.WorkOrderId = new SelectList(db.WorkOrders, "Id", "WO", workordersubmission.WorkOrderId);
return View(workordersubmission);
}
//
// POST: /WorkorderSubmissions/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(WorkOrderSubmission workordersubmission)
{
if (ModelState.IsValid)
{
db.Entry(workordersubmission).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ActivityRejectCodeId = new SelectList(db.ActivityRejectCodes, "Id", "RejectCodeId", workordersubmission.ActivityRejectCodeId);
ViewBag.PlatformStageId = new SelectList(db.PlatformStages.OrderBy(p => p.Name), "Id", "Name", workordersubmission.PlatformStageId);
ViewBag.StatusId = new SelectList(db.Status, "Id", "Name", workordersubmission.StatusId);
ViewBag.TechnicianShiftId = new SelectList(db.TechnicianShifts, "Id", "Description", workordersubmission.TechnicianShiftId);
ViewBag.WorkOrderId = new SelectList(db.WorkOrders, "Id", "WO", workordersubmission.WorkOrderId);
return View(workordersubmission);
}
Below is the AJAX call:
$(function () {
// Code that triggers when there is a change in Activity drop down.
$('#ActivityId').change(function () {
var activityId = $(this).val();
var url = 'GetRejectCodesByActivityJson';
// Empty the Reject Code drop down list.
$('#ActivityRejectCodeId').empty();
// Empty the Workstation, Platform, Part drop downs.
$('#WorkstationId').empty();
$('#PlatformId').empty();
$('#PartId').empty();
$('.showhide-workstation').show();
// AJAX call that re-populate Reject Code drop down depending on the Activity selected.
$.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: { activityId: activityId },
success: function (codes) {
$('#ActivityRejectCodeId').append('<option value=""></option>');
$.each(codes, function (i) {
$('#ActivityRejectCodeId').append('<option value = "' + codes[i].Value + '">' + codes[i].Text + '</option>')
});
},
error: function (ex) {
$('#ActivityRejectCodeId').append('<option value=""></option>');
}
}); // END $.ajax() on GetRejectCodesByActivityJson
url = 'GetWorkstationsByActivityJson';
// AJAX call that re-populate Workstation drop down depending on the Activity selected.
$.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: { activityId: activityId },
success: function (codes) {
$('#WorkstationId').append('<option value=""></option>');
$.each(codes, function (i) {
$('#WorkstationId').append('<option value = "' + codes[i].Value + '">' + codes[i].Text + '</option>');
});
},
error: function (ex) {
$('#WorkstationId').append('<option value=""></option>');
}
}); // END $.ajax() on GetRejectCodesByActivityJson
}); // END $('#ActivityId').change()
// Code that triggers when there is a change in Workstation drop down.
$('#WorkstationId').change(function () {
var activityId = $('#ActivityId').val();
var workstationId = $(this).val();
var url = 'GetPlatformsByWorkstationJson';
// Empty the Platform, Part drop downs.
$('#PlatformId').empty();
$('#PartId').empty();
$('.showhide-platform').show();
// AJAX call that re-populate Platform drop down depending on the Workstation selected.
$.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: { activityId: activityId, workstationId: workstationId },
success: function (codes) {
$('#PlatformId').append('<option value=""></option>');
$.each(codes, function (i) {
$('#PlatformId').append('<option value = "' + codes[i].Value + '">' + codes[i].Text + '</option>');
});
},
error: function (ex) {
$('#PlatformId').append('<option value=""></option>');
}
}); // END $.ajax() on GetPlatformsByWorkstationJson
}); // END $('#WorkstationId').change()

How to send message/notification to browser/client in Kendo Mvc Ajax Bound Grid (confirm update or create) ( by cookies)

how to send notification to client in kendo mvc ajax bound ,
i do not know if this is good way ..
of course you can add ModelState.AddModelError("notification","….msg.")
and …. But it tell to datasource ajax action failed.. So..
Addclass:
public class AjaxErrorMsg
{
public AjaxErrorMsg()
{
CssClass = "gray";
AutoHide = false;
AutoHideDelay = 200;
Kind = "error";
Title = "error";
}
public string Msg { get; set; }
public string Kind { get; set; }
public Boolean AutoHide { get; set; }
public Int32 AutoHideDelay { get; set; }
public string CssClass { get; set; }
public string Title { get; set; }
}
In controller
public void StoreMessageInCookie(string msg, Boolean isError = false, string msgDivClass = "", string preMessage = "", string msgTitle = "")
{
StoreMessageInCookie(new Exception(msg), isError, msgDivClass, preMessage, msgTitle);
}
public void StoreMessageInCookie(Exception ee, Boolean isError = false, string msgDivClass = "", string preMessage = "", string msgTitle = "")
{
List<AjaxErrorMsg> rs;
var js = new JavaScriptSerializer();
if (this.Response.Cookies[Common1.MsgCookie].HasKeys )
{
try
{
rs = js.Deserialize<List<AjaxErrorMsg>>(this.Response.Cookies[Common1.MsgCookie].Value);
}
catch
{
rs = new List<AjaxErrorMsg>();
}
}
else
{
rs = new List<AjaxErrorMsg>();
}
var msg0 = new AjaxErrorMsg();
if (isError)
{
msgDivClass = msgDivClass == "" ? "DivAlarmStyle6 fontMitra" : msgDivClass;
msg0.Kind = "error";
msg0.AutoHide = false;
msg0.Title = "Error";
}
else
{
msg0.Kind = "alert";
msg0.AutoHide = true;
msg0.Title = "Warning";
}
msg0.Title = msgTitle == "" ? msg0.Title : msgTitle;
msg0.Msg = preMessage + cm2.FilterMessageText(ee, IsAdminUser);
if (msgDivClass.Trim() != "")
msg0.Msg = Common1.WrapTextInDivWithClass(msg0.Msg, msgDivClass);
rs.Add(msg0);
this.Response.Cookies.Add(new HttpCookie(Common1.MsgCookie, js.Serialize(rs)));
}
cm2.FilterMessageText is function to remove database object name from error message string ..also include any inner exception message
Then when you what to send message use command
StoreMessageInCookie("Message 1 2 ! ");
And in your MainProject.js
Add all of code below
function createCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
}
else expires = "";
document.cookie = name + "=" + value + expires + "; path=/";
}
function eraseCookie(name) {
createCookie(name, "", -1);
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ')
c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0)
return c.substring(nameEQ.length, c.length);
}
return null;
}
function ReadAnShowCookieForDeliverMessages() {
try {
var listMsg = readCookie("CookieForDeliverMessages")
if (!!listMsg) {
eraseCookie("CookieForDeliverMessages");
ShowAndLogMessageListOfAjaxError($.parseJSON(listMsg));
}
} catch (ee) {
alert(" error in ReadAnShowCookieForDeliverMessages")
}
}
function ShowAndLogMessageListOfAjaxError(ListOfAjaxError) {
if (ListOfAjaxError == undefined)
return;
ListOfAjaxError.forEach(function (AjaxError) {
ShowAndLogMessageByAjaxErrorClass(AjaxError)
})
}
function ShowAndLogMessageByAjaxErrorClass(AjaxError) {
if ((AjaxError != undefined) && (AjaxError.Msg != "")) {
// I used freeow => https://github.com/pjdietz/Freeow
$("#freeow").freeow(AjaxError.Title, AjaxError.Msg, { classes: [AjaxError.CssClass, AjaxError.Kind], autoHide: AjaxError.AutoHide, autoHideDelay: AjaxError.AutoHideDelay });
// LogMsg(AjaxError.Msg, AjaxError.Title); function to log message on client
}
}
$(function () {
MyAjaxSetting();
ReadAnShowCookieForDeliverMessages();
}
function MyAjaxSetting() {
$(document).ajaxComplete(function (o) {
ReadAnShowCookieForDeliverMessages()
});
}

how i could iterate over json array of array

i want to iterate over a json array of arrays from th controller i want to know how i could iterate over it
i need help: nay could help me i'm new to json and mvc
//server code
var jsonData = new
{
rows =
(from bathymetrie in bathymetries
select new
{
count = bathymetries.Count,
Id = bathymetrie.Id,
date = (bathymetrie.displayedDate != null) ?
bathymetrie.displayedDate.ToString() : ""
}).ToArray()
};
//client code
success: function (data) {
bathyms = "{";
for (var i = 0; i < data[1].count; i++) {
bathyms += el[i].Id + " : " + el[i].date;
alert(el[i].Id);
alert(el[i].date);
console.log(el[i].date);
if (i != data[0].count) {
bathyms += ",";
}
}
bathyms += "}";
}
Your data is an object with single field row, which contains an array of objects. Thus, iteration should look like this:
for (var i = 0; i < data.rows.length; i++) {
var element = data.rows[i];
// use element.Id, element.count and element.date
Say if you have your model like this -
public class Data
{
public int Id { get; set; }
public int Count { get; set; }
public string Date { get; set; }
}
And you are returning JsonResult of Array object like this -
public ActionResult GetJson()
{
Data[] a = new Data[2];
a[0] = new Data() { Count = 10, Id = 1, Date = "2/19/2014" };
a[1] = new Data() { Count = 20, Id = 2, Date = "3/19/2014" };
return new JsonResult() { Data = a };
}
Then you can invoke this action in JQuery in the following way -
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
function submitForm() {
jQuery.ajax({
type: "POST",
url: "#Url.Action("GetJson")",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
$.each(data, function (key, value) {
alert(value.Id + ' ' + value.Count + ' ' + value.Date);
});
},
failure: function (errMsg) {
alert(errMsg);
}
});
}
</script>
<input type="button" value="Click" onclick="submitForm()" />
Please observe following code which will iterate array -
success: function (data) {
$.each(data, function (key, value) {
alert(value.Id + ' ' + value.Count + ' ' + value.Date);
});
Output would be N number of alerts based on N elements in array like below -

Forms authentication cookie is not persisting or is not getting past through an ajax request?

I am at a loss as to why my authentication cookie disappears. I am using Valums Ajax Upload in conjunction with a couple other ajax requests to build a user's avatar. It is very random as to when the cookie disappears. I can upload 4 files without an issue, then 2 files maybe (after another login). It seems after I call the CreateAvatar method, that is where there might be an issue, but like I said, it doesn't happen all the time. What am I missing?
JavaScript:
$(function () {
//This is the Upload Method
var fileCount = 0;
var uploader = new qq.FileUploader({
element: document.getElementById('file-uploader'),
action: '/Admin/Avatar/AvatarUpload',
debug: true,
params: {
'userId': '#ViewBag.UserId'
},
onSubmit: function (id, fileName) {
fileCount++;
},
onComplete: function (id, fileName, responseJson) {
if (responseJson.success) {
//fileCount--;
if (createAvatar(responseJson.file, responseJson.imageId)) {
fileCount--;
} else {
fileCount--;
//alert('There was an error when trying to save ' + fileName);
}
} else {
$("span.qq-upload-file:contains(" + fileName + ")").text(responseJson.errorMessage);
fileCount--;
}
if (fileCount == 0) {
}
},
onCancel: function (id, fileName) {
fileCount--;
if (fileCount == 0) {
parent.$.fn.colorbox.close();
}
}
});
});
//This Creates the Avatar Object
function createAvatar(fileName, imageId) {
var avatarUploadModel = {
UploadFileName: fileName,
UserId: '#ViewBag.UserId',
ImageId: imageId
};
$.ajax({
url: '/Admin/Avatar/CreateAvatar/',
type: 'POST',
cache: false,
timeout: 100000,
data: JSON.stringify(avatarUploadModel),
contentType: 'application/json; charset=utf-8',
dataType: "json",
error: function (xhr, status, error) {
alert(error + " " + status);
},
success: function (data) {
if (data.success) {
loadAvatar(data.avatarModel);
return true;
} else {
return false;
}
}
});
}
//This loads the partial to view the avatar after upload
function loadAvatar(avatarModel) {
$.ajax({
url: '/Admin/Avatar/AvatarEdit',
type: 'GET',
cache: false,
timeout: 100000,
data: avatarModel,
dataType: "html",
error: function (xhr, status, error) {
alert(error + " " + status);
},
success: function (data) {
$("#avatarOriginal").html(data);
}
});
}
Login Method:
var user = _userService.GetByUserName(model.Username);
var authTicket = new
FormsAuthenticationTicket(1, //version
user.Id.ToString(), // user name
DateTime.Now,
DateTime.Now.AddMinutes(40), //Expiration
model.RememberMe, //Persistent,
user.Username);
var encTicket = FormsAuthentication.Encrypt(authTicket);
HttpContext.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
return Json(new {success = true, url = model.ReturnUrl}, JsonRequestBehavior.AllowGet);
Upload Method on Controller:
[HttpPost]
public ActionResult AvatarUpload(HttpPostedFileBase fileData)
{
var id = Guid.NewGuid();
string fileName;
var serverPath = Server.MapPath("~/Areas/Admin/TemporaryUploads/");
if (fileData != null)
{
var fileRenamed = System.IO.Path.GetFileName(id + "_" + fileData.FileName);
fileName = Server.MapPath("~/Areas/Admin/TemporaryUploads/" + fileRenamed);
fileData.SaveAs(fileName);
}
else
{
var ajaxUploadFileData = Request["qqfile"];
fileName = Path.Combine(serverPath, id + "_" + Path.GetFileName(ajaxUploadFileData));
using (var output = System.IO.File.Create(fileName))
{
Request.InputStream.CopyTo(output);
}
}
return Json(new {success = true, file = fileName, imageId = id}, JsonRequestBehavior.AllowGet);
}
Create Avatar Method:
[HttpPost]
public ActionResult CreateAvatar(AvatarModel avatarModel)
{
try
{
var image = new WebImage(avatarModel.UploadFileName).Resize(400, 400, true);
var imageFileName = Path.GetFileName(avatarModel.UploadFileName);
var avatar = new Domain.YogaDiVitaContext.Model.Avatar()
{
CreatedById = Guid.Parse(HttpContext.User.Identity.Name),
ModifiedById = Guid.Parse(HttpContext.User.Identity.Name),
UserId = avatarModel.UserId,
Image = new Image()
{
CreatedById = Guid.Parse(HttpContext.User.Identity.Name),
ModifiedById = Guid.Parse(HttpContext.User.Identity.Name),
OriginalImageRelativePath = "original/" + imageFileName
}
};
var user = UserService.FindById(avatarModel.UserId);
if (user.Avatar != null)
RemoveAvatar(user.Avatar);
avatar = _avatarService.Create(avatar);
user.Avatar = avatar;
UserService.Update(user);
var basePath = Server.MapPath("~/" + avatar.ToAvatarBasePath(GlobalVariables.AvatarPath));
Directory.CreateDirectory(basePath);
Directory.CreateDirectory(basePath + "/thumbnail");
Directory.CreateDirectory(basePath + "/fullsize");
Directory.CreateDirectory(basePath + "/original");
image.Save(Server.MapPath("~/" + avatar.ToAvatarOriginalPath(GlobalVariables.AvatarPath)));
avatarModel.Width = image.Width;
avatarModel.Height = image.Height;
avatarModel.Top = image.Height*0.1;
avatarModel.Left = image.Width*0.9;
avatarModel.Right = image.Width*0.9;
avatarModel.Bottom = image.Height*0.9;
avatarModel.OriginalImagePath = "/" + avatar.ToAvatarOriginalPath(GlobalVariables.AvatarPath);
System.IO.File.Delete(avatarModel.UploadFileName);
return Json(new {success = true, avatarModel}, JsonRequestBehavior.AllowGet);
}
catch (Exception exception)
{
return Json(new {message = exception.Message}, JsonRequestBehavior.AllowGet);
}
}
Load Avatar Partial:
public ActionResult AvatarEdit(AvatarModel avatarModel)
{
return PartialView("AvatarCropPartial", avatarModel);
}

How to read modelstate errors when returned by Json?

How can I display ModelState errors returned by JSON?
I want to do something like this:
if (!ValidateLogOn(Name, currentPassword))
{
ModelState.AddModelError("_FORM", "Username or password is incorrect.");
//Return a json object to the javascript
return Json(new { ModelState });
}
What must be my code in the view to read the ModelState errors and display them?
My actual code in the view to read the JSON values is as follows:
function createCategoryComplete(e) {
var obj = e.get_object();
alert(obj.Values);
}
This is draft code but the same idea works for me in production.
The main idea here is that Json errors have predefined tag names, that no normal objects will have. For errors validation errors HTML is re-created using JavaScript (both top summary and form elements highlighting).
Server side:
public static JsonResult JsonValidation(this ModelStateDictionary state)
{
return new JsonResult
{
Data = new
{
Tag = "ValidationError",
State = from e in state
where e.Value.Errors.Count > 0
select new
{
Name = e.Key,
Errors = e.Value.Errors.Select(x => x.ErrorMessage)
.Concat(e.Value.Errors.Where(x => x.Exception != null).Select(x => x.Exception.Message))
}
}
};
}
in action:
if (!ModelState.IsValid && Request.IsAjaxRequest())
return ModelState.JsonValidation();
Client side:
function getValidationSummary() {
var el = $(".validation-summary-errors");
if (el.length == 0) {
$(".title-separator").after("<div><ul class='validation-summary-errors ui-state-error'></ul></div>");
el = $(".validation-summary-errors");
}
return el;
}
function getResponseValidationObject(response) {
if (response && response.Tag && response.Tag == "ValidationError")
return response;
return null;
}
function CheckValidationErrorResponse(response, form, summaryElement) {
var data = getResponseValidationObject(response);
if (!data) return;
var list = summaryElement || getValidationSummary();
list.html('');
$.each(data.State, function(i, item) {
list.append("<li>" + item.Errors.join("</li><li>") + "</li>");
if (form && item.Name.length > 0)
$(form).find("*[name='" + item.Name + "']").addClass("ui-state-error");
});
}
$.ajax(... function(response) {
CheckValidationErrorResponse(xhr.responseText); } );
Why not return the original ModelState object to the client, and then use jQuery to read the values. To me it looks much simpler, and uses the common data structure (.net's ModelState)
C#:
return Json(ModelState);
js:
var message = "";
if (e.response.length > 0) {
$.each(e.response, function(i, fieldItem) {
$.each(fieldItem.Value.Errors, function(j, errItem) {
message += errItem.ErrorMessage;
});
message += "\n";
});
alert(message);
}
this is a tiny tweak to queen3's client side code which handles specific validation messages, and creates a similar document to that created by MVC3:
function getValidationSummary() {
var $el = $(".validation-summary-errors > ul");
if ($el.length == 0) {
$el = $("<div class='validation-summary-errors'><ul></ul></div>")
.hide()
.insertBefore('fieldset:first')
.find('ul');
}
return $el;
}
function getResponseValidationObject(response) {
if (response && response.Tag && response.Tag == "ValidationError")
return response;
return null;
}
function isValidationErrorResponse(response, form, summaryElement) {
var $list,
data = getResponseValidationObject(response);
if (!data) return false;
$list = summaryElement || getValidationSummary();
$list.html('');
$.each(data.State, function (i, item) {
var $val, lblTxt, errorList ="";
if (item.Name) {
$val = $(".field-validation-valid,.field-validation-error")
.first("[data-valmsg-for=" + item.Name + "]")
.removeClass("field-validation-valid")
.addClass("field-validation-error");
$("input[name=" + item.Name + "]").addClass("input-validation-error")
lblTxt = $("label[for=" + item.Name + "]").text();
if (lblTxt) { lblTxt += ": "; }
}
if ($val.length) {
$val.text(item.Errors.shift());
if (!item.Errors.length) { return; }
}
$.each(item.Errors, function (c,val) {
errorList += "<li>" + lblTxt + val + "</li>";
});
$list.append(errorList);
});
if ($list.find("li:first").length) {$list.closest("div").show(); }
return true;
}
See below for code with a few amendments to Brent's answer. CheckValidationErrorResponse looks for the Validation Summary regardless of whether it's in the valid or invalid state, and inserts it if not found. If validation errors are found in the response, it applies the validation-summary-errors class to the Summary, else it applies validation-summary-valid. It assumes CSS is present to control the visibility of the Summary.
The code clears existing instances of field-validation-error, and reapplies them for errors found in the response.
function getValidationSummary(form) {
var $summ = $(form).find('*[data-valmsg-summary="true"]');
if ($summ.length == 0)
{
$summ = $('<div class="validation-summary-valid" data-valmsg-summary="true"><ul></ul></div>');
$summ.appendTo(form);
}
return $summ;
}
function getValidationList(summary) {
var $list = $(summary).children('ul');
if ($list.length == 0) {
$list = $('<ul></ul>');
$list.appendTo(summary);
}
return $list;
}
function getResponseValidationErrors(data) {
if (data && data.ModelErrors && data.ModelErrors.length > 0)
return data.ModelErrors;
return null;
}
function CheckValidationErrorResponse(data, form, summaryElement) {
var errors = getResponseValidationErrors(data);
var $summ = summaryElement || getValidationSummary(form);
var $list = getValidationList($summ);
$list.html('');
$(form).find(".field-validation-error")
.removeClass("field-validation-error")
.addClass("field-validation-valid");
if (!errors)
{
$summ.removeClass('validation-summary-errors').addClass('validation-summary-valid');
return false;
}
$.each(errors, function (i, item) {
var $val, $input, errorList = "";
if (item.Name) {
$val = $(form).find(".field-validation-valid, .field-validation-error")
.filter("[data-valmsg-for=" + item.Name + "]")
.removeClass("field-validation-valid")
.addClass("field-validation-error");
$input = $(form).find("*[name='" + item.Name + "']");
if (!$input.is(":hidden") && !$val.length)
{
$input.parent().append("<span class='field-validation-error' data-valmsg-for='" + item.Name + "' data-valmsg-replace='false'>*</span>");
}
$input.addClass("input-validation-error");
}
$.each(item.Errors, function (c, err) {
errorList += "<li>" + err + "</li>";
});
$list.append(errorList);
});
$summ.removeClass('validation-summary-valid').addClass('validation-summary-errors');
return true;
}
C#
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
JavaScript
$.ajax({
type: "GET",
url: "/api/xxxxx",
async: 'false',
error: function (xhr, status, err) {
if (xhr.status == 400) {
DisplayModelStateErrors(xhr.responseJSON.ModelState);
}
},
....
function DisplayModelStateErrors(modelState) {
var message = "";
var propStrings = Object.keys(modelState);
$.each(propStrings, function (i, propString) {
var propErrors = modelState[propString];
$.each(propErrors, function (j, propError) {
message += propError;
});
message += "\n";
});
alert(message);
};
If you are returning JSON, you cannot use ModelState. Everything that the view needs should be contained inside the JSON string. So instead of adding the error to the ModelState you could add it to the model you are serializing:
public ActionResult Index()
{
return Json(new
{
errorControl = "_FORM",
errorMessage = "Username or password is incorrect.",
someOtherProperty = "some other value"
});
}

Resources