This is a follow up to a previous question that I had before about passing an error back to the client, but also pertains to the ModelState.
Has anyone successful used the Nerd Dinner approach, but with Ajax? So Nerd Dinner does an update as so.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues)
{
Dinner dinner = dinnerRepository.GetDinner(id);
try
{
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch
{
foreach (var issue in dinner.GetRuleViolations()) {
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(dinner);
}
}
Using jQuery $.ajax
function hijack(form, callback, errorFunction, format) {
$.ajax({
url: form.action,
type: form.method,
dataType: format,
data: $(form).serialize(),
success: callback,
error: function(xhr, textStatus, errorThrown) {
errorFunction(xhr, textStatus, errorThrown);
}
});
}
Ajax, the "try" part of the controller becomes
try
{
UpdateModel(dinner);
dinnerRepository.Save();
return PartialView("PartialDetails", new { id=dinner.DinnerID });
}
, but what do you do about the catch part?
A simple error handling solution to send back an error would be
catch(Exception ex)
{
Response.StatusCode = 500;
return Content("An Error occured.");
//throw ex;
}
, but that doesn't pass through the robust modelstate built into MVC. I thought of a number of options, but I really want 2 things:
- I want the error to be handled in jQuery's error attribute.
- I want to use built in ASP.Net MVC validation logic as much as possible.
Is this possible? If not, what are the best alternatives that you know of?
Many thanks.
Update I haven't marked this as answered yet, because I haven't yet implemented what I think will work best.
I have decided that I don't really like the success => send refreshed list, failure => send error message approach that I was taking. I did this to reduce the number of calls, but a refreshed list is really being set to the page. Trying to do both tightly binds the popup to its overall page.
I am going to add a custom jQuery event refresh the master page list when the dialog closes. In essence, it's the observer pattern. I like the idea that the page says to the popup "tell me when you're done" (aka closed), without having to tell the popup why. It does require an additional call, but I don't see that as a big issue.
I'm still not sure how well that I like/dislike server-side validation and I'm considering going with client-side only validation. While server side validation seems like clean layering, it also has a number of problems, including:
1) It puts quality checks at the end, instead of the beginning. An analogy to manufacturing would be a car that's tested when it arrives at the dealer, instead at the points in the process where it's being built.
2) It violates the intent of Ajax. Ajax isn't just about sending asynchronous events, it's also about sending only what I need and receiving only what I need. Sending back the entire modelstate in order to provide error details doesn't seem to go with Ajax.
What I'm thinking about doing is having client-side only validation, but that server code and a custom viewmodel can be used to tell the client how to dynamically create those validation rules.
I also suspect that a dynamic language like IronRuby or IronPython might offer a more elegant way to solve these problems, but it could be a little longer before I look into that possibility.