Ajax form validation - asp.net-mvc

Is there any convenient way to integrate ASP.NET MVC validation (I am primarily interested in Fluent Validation) with forms submitting by Ajax?

The easiest way to achieve this is to place those forms inside partials and then submit them using AJAX. The controller action which will handle the POST will check if the model is valid and if not return the partial in order to show the validation errors. For example:
<div id="myform_container">
<!-- The _Foo partial will contain a form -->
#Html.Partial("_Foo")
</div>
and a controller action which will handle the submission:
[HttpPost]
public ActionResult Foo(SomeViewModel model)
{
if (!ModelState.IsValid)
{
return PartialView("_Foo", model);
}
// TODO: process the results and inform the user that everything went fine:
return Json(new { success = true });
}
Now all that's left is to AJAXify this form in a separate javascript file:
$(function() {
// Use delegate to preserve the .submit handler when we refresh the container
$('#myform_container').delegate('form', 'submit', function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
if (result.success) {
// the server returned JSON
alert('thanks for submitting');
} else {
// the server returned the partial => update the DOM
$('#myform_container').html(result);
}
}
});
return false;
});
});

Related

mvc display text after post and keep data in form

How can I after posting a form in my mvc page display a message and keeping the added/selected data in the form? I have tried to render a partialview but that renders a blank page which only contains the actual partialview.
<div id="resultTarget">
#Html.Partial("CalculationResult", new Model.CalculatedPrice())
</div>
[HttpPost]
public PartialViewResult GetPrice(FormCollection formCollection)
{
// This renders only the partialview
return PartialView("CalculationResult", model);
}
If you reload the page with a form post the data will be lost. Create a view model and bind the controls to specific properties using #Html.TextBoxFor(), #Html.ListBoxFor() etc.
Now instead of submitting the form back to the controller, use javascript to post data back to the controller on a button click function.
See below code :
In Button Click function :
var modelObj = {};
modelObj.prop1 = $('#txtField1').val();
modelObj.prop2 = $('#txtField2').val();
var postObj = JSON.stringify(modelObj); // convert object to json
$.ajax({
type: "POST",
traditional: true,
dataType: "json",
url: "/SomeController/GetPrice",
data: { formCollection: postObj }
cache: false,
success: function (data) {
if (data) {
//Some Code if post success
}
else {
// Some code if post failed
}
}});
In SomeController :
[HttpPost]
public JSonResult GetPrice(FormCollection formCollection)
{
// Do your action with the formCollection object here
// if(action.success)
{
return JSon(true);
}
return JSon(false);
}
This way you can prevent reloading of the page and keep the data in the forms as such.

Using MVC4 how can you submit the [HttpPost] action without a submit button?

Typically I would create a submit button to post data, but in this case I want the [HttpPost] action to post on page load. This page is collecting data from other sources and there is no need for the user to hit submit.
simply use ajax call, imagine that a get action returns the list of tags like this:
public ActionResult Index()
{
var tags = _tagRepository.GetAllTag();
return View(tags);
}
now in the view of index you have all tags, and also want to add the remove capability, now you can do this by ajax call:
#model IList<Blog.Domain.Model.Tag>
//list of tags here
<script type="text/javascript">
$(function () {
$(".delete").click(function (e) {
e.preventDefault();
var link = this.href;
$.ajax({
type: 'Post',
url: link,
success: function (data) { }
});
});
});
</script>
and about the post action:
[HttpPost]
public JsonResult Delete(int tagId)
{
if (ModelState.IsValid)
{
_tagRepository.RemoveTag(tagId);
_tagRepository.Save();
RedirectToAction("Index");
}
return Json("");
}
If you don't want to use AJAX, you can simply submit the form with jQuery:
$('form').submit();

Return PartialView from JsonResult ActionMethod back to ajax post and display that PartialView as a Modal pop-up

I am trying to return back PartialView or any other view from action method back to ajax post. I wanted to display the contents ParitalView as a Jquery Modal pop-up from ajax success function or whichever way its possible.
'MyRegistrationView' with Registration Form on it has below mentioned ajax post call on form submit button.
$.ajax({
url: url, //http://localhost/MyRegistration/RegisterUser
type: 'POST',
dataType: 'json',
data: ko.toJSON(RegistrationInfoModel),
contentType: "application/json; charset=utf-8",
success: function (result) {
//Do something
},
error: function (request, status, error) {
//Do something
}
});
The above ajax call goes to my Controller named " MyRegistrationController" with the action method as below.
[HttpPost]
public JsonResult RegisterUser(RegistrationInfo model)
{
//Register User
....
if(successful)
{
return Json(new { data = PartialView("_ShowSuccessfulModalPartial") });
}
}
Now
how can i get back the 'content' of '_ShowSuccessfulModalPartial' in
'Success' function of ajax and show that as the Modal Pop up on that
same registration page.
If i want to return/redirect it to some other view how can i do it
if i have JsonResult as return type of my ActionMethod.
How I can send back the ModalErrors from registration process back
to my view and show them under ValidationSummary.
(Note: If I don't use JsonResult as return type i get ajax 'parseerror' Unexpected token <)
You can return a partial view instead of a json.
In your main view you shoudl add the dialog html like this (assumming you're using jQueryUI):
<div id="dialog-confirm" title="Your title">
<div id="dialog-content"></div>
</div>
Make sure you initialize the dialog.
$(document).ready(function() {
$("#dialog-confirm").dialog();
});
In the controller you might need to return a partial view:
[HttpPost]
public virtual ActionResult RegisterUser(RegistrationInfo model)
{
var model = //Method to get a ViewModel for the partial view in case it's needed.
return PartialView("PartialViewName", model);
}
Then when you do your ajax request, you append the partial view to the dialog and then show it.
$.ajax({
url: url,
type: 'POST',
dataType: 'json',
data: ko.toJSON(RegistrationInfoModel),
contentType: "application/json; charset=utf-8",
success: function (result) {
$("#dialog-content").empty();
$("#dialog-content").html(result);
$("#dialog-confirm").dialog("open");
},
error: function (request, status, error) {
//Do something
}
});
Hope this helps.

How to manage MVC AJAX responses when in a jQuery dialog

Here is my problem:
Inside a jQuery dialog I have the following code:
<%:Ajax.ActionLink("Yes", "SendClaim", "Claim", new { id = Model.ExpenseId }, new AjaxOptions { UpdateTargetId = "dialog" }, new { #class = "button" })%>
When stuff fails in the controller based on roles I return a partial view that replaces the existing dialog (see UpdateTargetId = "dialog").
When everything works I want to do a redirect to another page (an index of all claims) to stop the user performing additional actions but this entire page is rendered inside the jQuery dialog due to it being an ajax request with an update id.
What is the correct way to approach the problem?
I'm a bit of a novice, but I find I have more control with the following approach instead of using Ajax.ActionLink. Hopefully it helps and I have understood what you want to do correctly.
Claim Controller:
[AcceptVerbs(HttpVerbs.Post)]
public Json Send(int expenseId)
{
// Check user stuff
if(valid)
// do stuff
return new Json(true, JsonRequestBehavior.AllowGet);
else
return new Json(false, JsonRequestBehavior.AllowGet);
}
jQuery
function submitClaim() {
$.ajax({
url: "/Claim/Send",
type: "POST",
dataType: "json",
data: { 'expenseId': <%=Model.ExpenseId> },
success: function (data) {
if(data) { // if successful, redirect
document.location = "Claim/Index";
}
else { //load your partial view into your dialog
$("#idOfYourDialog").load('Claim/Error/');
}
},
error: function (xhr) { }
});
}
html
Submit
Returned an 'All OK' dialog and had the following javascript when the user clicks the ok button:
function redirect() {
document.location = "<%:(String)ViewBag.Redirect %>";
}
$(document).ready(function() {
$(".ui-dialog-titlebar-close").click(function() {
redirect();
});
});
Seems unavoidable - you can't seem to do an RedirectToAction when the controller action has been called from Ajax.ActionLink as the response will be stuck into the updatetargetid.

MVC: I delete a row from my grid, but my page does not refresh

I have a Html.Helper that I use to delete rows from my grid.
It calls the following method on my controller;
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult Delete(int _employeeOtherLeaveId)
{
EmployeeOtherLeaf.Delete(_employeeOtherLeaveId);
return RedirectToAction("Payroll");
}
This calls the GET method on my controller which I would expect to refresh the view of my grid, but it doesn't. When I manually refresh I see the row has in fact been deleted. Why is this?
[HttpGet]
public ActionResult Payroll()
{
if ((SessionObjects.PeriodStartDate > DateTime.MinValue) && (SessionObjects.PeriodEndDate > DateTime.MinValue))
if (SessionObjects.PayrollSelectedEmployeeId == 0)
return View(new PayrollViewModel()
{
PeriodStartDate = SessionObjects.PeriodStartDate,
PeriodEndDate = SessionObjects.PeriodEndDate
});
else
return View(new PayrollViewModel(
SessionObjects.PeriodStartDate,
SessionObjects.PeriodEndDate,
SessionObjects.PayrollSelectedEmployeeId
));
return View();
}
This will depend how you are calling the DELETE action. Judging from your previous question and the answer you accepted I suppose that you are doing the following:
onclick="$.ajax({url: this.href, type: 'DELETE'}); return false;"
which obviously is insufficient as you are sending the AJAX request to delete but you aren't handling the success event to update the DOM. So you might need to do this:
$.ajax({
url: this.href,
type: 'DELETE',
success: function(result) {
// update some DOM element with the result returned by the
// server. So supposing that you have some <div id="someContainer">
// that will contain the part of the DOM you want updated:
$('#someContainer').html(result);
}
});
return false;
Now obviously stuffing all this javascript inside the HTML as you were using your custom helper is ugly. Personally I would use unobtrusive javascript. I would have my helper generate a normal anchor with a class and then in a completely separate javascript file I would AJAXify this link:
$(function() {
// AJAXify the anchor with the delete class that would
// be generated by your custom helper
$('.delete').click(function() {
$.ajax({
url: this.href,
type: 'DELETE',
success: function(result) {
// update some DOM element with the result returned by the
// server. So supposing that you have some <div id="someContainer">
// that will contain the part of the DOM you want updated:
$('#someContainer').html(result);
}
});
return false;
});
});

Resources