Model Binding and posting form via ajax - asp.net-mvc-3

I want to post a form via ajax call also model will be passed into the action method, but want to get Model errors via json. How can I do this?

You could write a custom action filter:
public class HandleJsonErrors : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var modelState = (filterContext.Controller as Controller).ModelState;
if (!modelState.IsValid)
{
// if the model is not valid prepare some JSON response
// including the modelstate errors and cancel the execution
// of the action.
// TODO: This JSON could be further flattened/simplified
var errors = modelState
.Where(x => x.Value.Errors.Count > 0)
.Select(x => new
{
x.Key,
x.Value.Errors
});
filterContext.Result = new JsonResult
{
Data = new { isvalid = false, errors = errors }
};
}
}
}
and then put it into action.
Model:
public class MyViewModel
{
[StringLength(10, MinimumLength = 5)]
public string Foo { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[HandleJsonErrors]
public ActionResult Index(MyViewModel model)
{
// if you get this far the model was valid => process it
// and return some result
return Json(new { isvalid = true, success = "ok" });
}
}
and finally the request:
$.ajax({
url: '#Url.Action("Index")',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
foo: 'abc'
}),
success: function (result) {
if (!result.isvalid) {
alert(result.errors[0].Errors[0].ErrorMessage);
} else {
alert(result.success);
}
}
});

Something like this?
$.ajax({
type: "POST",
url: $('#dialogform form').attr("action"),
data: $('#dialogform form').serialize(),
success: function (data) {
if(data.Success){
log.info("Successfully saved");
window.close();
}
else {
log.error("Save failed");
alert(data.ErrorMessage);
},
error: function(data){
alert("Error");
}
});
[HttpPost]
public JsonResult SaveServiceReport(Model model)
{
try
{
//
}
catch(Exception ex)
{
return Json(new AdminResponse { Success = false, ErrorMessage = "Failed" }, JsonRequestBehavior.AllowGet);
}

Related

return partial view from async method

I've an async action method that return a partial view.
this action method called from a function with ajax.
my problem : when this method invoked every thing looks good except returned partial view.
I got error 500.
this is my action method Code :
[HttpPost]
public async Task<ActionResult> ChangeStateGroup(int[] lstCustomerServiceId, int newState)
{
int _counter = 0;
try
{
var _isOk = await CommonFunctions.ChangeState(_customerServiceId, _stateId, string.Empty);
if (_isOk)
{
//------do somthing
}
}
TempData[MyAlerts.SUCCESS] = string.Format("succeed Operation {0}", _counter);
}
catch (Exception ex)
{
TempData[MyAlerts.ERROR] = string.Format("Error: {0}", ex.Message);
}
return PartialView("_AlertsPartial");
}
and this is my jquery Code:
function postCustomerChangeStateGroup(lstCustomersId) {
var arrCustomersId = lstCustomersId.split(',');
$.ajax({
type: "POST",
url: "../Customer/ChangeStateGroup",
data: {
lstCustomerServiceId: arrCustomersId,
newState: $("#fk_state").val()
},
success: function (data) {
if (data.indexOf("error") !== -1) {
$("#inlineAlert_Wrapper").append(data);
}
else {
getCustomerReport();
$('#modal-container').modal('toggle');
$("#alert_Wrapper").append(data);
}
},
failure: function (errMsg) {
alert("An Error Accoured: " + errMsg);
}
});
}
Partial views cannot be asynchronous in ASP.NET pre-Core. You can have asynchronous partial views in ASP.NET Core.
So, your options are:
Update to ASP.NET Core.
Remove the asynchronous code and make it synchronous instead.
Error 500 means the error inside of the action.It maybe because ot the empty input parameters. Check them in debugger and if they are empty,
try to use application/json content type,sometimes it works better
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Customer/ChangeStateGroup",
data: JSON.stringify( {
lstCustomerServiceId: arrCustomersId,
newState: $("#fk_state").val()
}),
success: function (data) {
....
create viewModel
public class ViewModel
{
public int[] lstCustomerServiceId {get; set;}
public int newState {get; set;}
}
and fix the action
public async Task<ActionResult> ChangeStateGroup([FromBody] ViewModel model)

Can't post array back to action method mvc

I'm trying to post an array of values back to my action method, but with no luck as I'm getting a null for 'ParcelList'. Upload Files argument is being populated, just having a problem with ParcelList.
//ParcelList returning null
public ActionResult Add(AddShipmentVM model, ParcelVM[] ParcelList, HttpPostedFileBase[] UploadFiles )
{
if (ModelState.IsValid)
{
return RedirectToAction("Home", "CustomClearence");
}
return View(model);
}
ParcelVM
public class ParcelVM
{
[Required(ErrorMessageResourceType = typeof(AddShipmentVM), ErrorMessageResourceName = "RequiredValue")]
public string TrackTrace { get; set; }
[Required(ErrorMessageResourceType = typeof(AddShipmentVM), ErrorMessageResourceName = "RequiredValue")]
[RegularExpression(#"^\d{0,3}\.?(\d{3,3})*,?\d{1,2}$", ErrorMessageResourceType = typeof(AddShipmentVM), ErrorMessageResourceName = "InvalidWeight")]
public string GrossWeight { get; set; }
public decimal Parcelno { get; set; }
}
Ajax
When user clicks on finish, submit form
$(".actions a[href=#finish]").click(function () {
var form = jQuery('#addShipmentForm').serializeObject();
var parcelList = $.parseJSON(ko.toJSON(viewModel.parcelList()));
var tariffList = $.parseJSON(ko.toJSON(viewModel.tariffList()));
var dashBoardurl = '#Url.Action("Home","Shipment")'
var tariffObject = JSON.stringify({ TariffList: tariffList });
$('#uploadDocument input[type=file]')[0].files }
var UploadFiles = { UploadFiles: $('#uploadDocument input[type=file]')[0].files }
$.extend(form, { FinancialAndCustomsModel: tariffObject });
$.extend(form, { ParcelList: parcelList });
$.extend(form, UploadFiles);
$.ajax({
type: "POST",
data: form,
contentType: false,
success: function (result) {
if (result.status == "success") {
$(location).attr('href', dashBoardurl);
}
else {
//$(location).attr('href', addRequestUrl);
}
},
cache: false,
processData: false
});
});

Pass ViewModel + Parameter to action using ajax call

How do I pass a view model and another parameter to my action method using jquery ajax?
with what I'm doing now, the action method is not being called. I think the cause is probably because the parameters are not being passed correctly in the data object of the jquery ajax call:
jQuery ajax:
$('#form-login').submit(function (event) {
event.preventDefault();
$.ajax({
url: "/Account/LogOn/",
data: $('#form-login').serialize(),
contentType: 'application/json; charset=utf-8',
success: function (data) {
if (data.userAuthenticated) {
window.location.href = data.url;
} else {
formBlock.clearMessages();
displayError($('#errorcred').val());
}
},
error: function () {
formBlock.clearMessages();
displayError($('#errorserver').val());
}
});
});
Action method (which accepts the view model and another parameter):
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
// Validate the email and password
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
if (Request.IsAjaxRequest())
{
return Json(new { userAuthenticated = true, url = returnUrl, isRedirect = true });
}
else
{
return Redirect(returnUrl);
}
}
else
{
if (Request.IsAjaxRequest())
{
return Json(new { userAuthenticated = true, url = Url.Action("Index", "Home"), isRedirect = true });
}
else
{
return RedirectToAction("Index", "Home");
}
}
}
}
else
{
if (Request.IsAjaxRequest())
{
return Json(new { userAuthenticated = false, url = Url.Action("LogOn", "Account") });
}
else
{
ModelState.AddModelError("", adm.ErrorUserNamePassword);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Remove the following from the $.ajax call:
contentType: 'application/json; charset=utf-8',
You have specified application/json encoding but the $('#form-login').serialize() function is sending application/x-www-form-urlencoded content.
As far as sending the returnUrl parameter is concerned, you could simply read it from the form action where it should be present (if you used the Html.BeginForm() helper):
$.ajax({
url: this.action,
...
});
Also you probably want to rename the event variable with something else as this is a reserved word in javascript:
$('#form-login').submit(function (e) {
e.preventDefault();
...
});
The only way I have found to do this is to just include the second parameter in your viewmodel and continue to serialize your form the way you are doing now.

MVC3 Ajax Get String and post it back

on MVC3 Page load i have a String in a Model which is should be the JSONObj.
private string CreateJSONObj(Model model)
{ return "{ name: 'test', Items: [{ test: 1 }, { test: 2 }]"; }
Model.jsonModel = CreateJSONObj(model);
Now i want to implement it in my page:
<script>var jsModel = eval('#Model.jsonModel');
var jsonModel = $.toJSON(jsModel);
$.ajax({
url: 'Page/SetJSON/',
type: "POST",
data: jsonModel,
datatype: "json",
contentType: "application/json; charset=utf-8",
success: function () {
$('#test').html('Saved').fadeIn(),
},
error: function () {
$("#test").html("error"),
}
});</script>
But the Controller gets a null Object. If i write the jsonstring into the script everthing is fine.
Should i use eval? But var jsModel = eval('#Model.jsonModel'); has no effect. What is wrong? :-)
You don't need to use a CreateJSONObj method or a jsonModel property on your model. In order to use it in the view you could simply use the JavaScriptSerializer class which will convert the server side model object into a javascript object:
<script type="text/javascript">
var jsModel = #Html.Raw(new JavaScriptSerializer().Serialize(Model));
$.ajax({
url: '#Url.Action("SetJSON", "Page")',
type: 'POST',
data: JSON.stringify(jsModel),
contentType: 'application/json; charset=utf-8',
success: function () {
$('#test').html('Saved').fadeIn();
},
error: function () {
$('#test').html('error');
}
});
</script>
This will successfully send the model to the following controller action:
[HttpPost]
public ActionResult SetJSON(Model model)
{
...
}
where the Model class contains all the necessary information:
public class Model
{
public string Name { get; set; }
public IEnumerable<Item> Items { get; set; }
}
public class Item
{
public int Test { get; set; }
}
and the controller:
public class PageController: Controller
{
// Used to render the view
public class Index()
{
var model = new Model
{
Name = "Test",
Items = new[]
{
new Item { Test = 1 },
new Item { Test = 2 },
}
};
return View(model);
}
// Used to handle the AJAX POST request
[HttpPost]
public ActionResult SetJSON(Model model)
{
...
}
}

MVC Return Partial View as JSON

Is there a way to return an HTML string from rendering a partial as part of a JSON response from MVC?
public ActionResult ReturnSpecialJsonIfInvalid(AwesomenessModel model)
{
if (ModelState.IsValid)
{
if(Request.IsAjaxRequest()
return PartialView("NotEvil", model);
return View(model)
}
if(Request.IsAjaxRequest())
{
return Json(new { error=true, message = PartialView("Evil",model)});
}
return View(model);
}
You can extract the html string from the PartialViewResult object, similar to the answer to this thread:
Render a view as a string
PartialViewResult and ViewResult both derive from ViewResultBase, so the same method should work on both.
Using the code from the thread above, you would be able to use:
public ActionResult ReturnSpecialJsonIfInvalid(AwesomenessModel model)
{
if (ModelState.IsValid)
{
if(Request.IsAjaxRequest())
return PartialView("NotEvil", model);
return View(model)
}
if(Request.IsAjaxRequest())
{
return Json(new { error = true, message = RenderViewToString(PartialView("Evil", model))});
}
return View(model);
}
Instead of RenderViewToString I prefer a approach like
return Json(new { Url = Url.Action("Evil", model) });
then you can catch the result in your javascript and do something like
success: function(data) {
$.post(data.Url, function(partial) {
$('#IdOfDivToUpdate').html(partial);
});
}
$(function () {
$("select#ExamID").change(function (evt) {
var classid = $('#ClassId').val();
var StudentId = $('#StudentId').val();
$.ajax({
url: "/StudentMarks/ShowStudentSubjects",
type: 'POST',
data: { classId: classid, StudentId: StudentId, ExamID: $(this).val() },
success: function (result) {
$('#ShowStudentSubjects').html(result);
},
error: function (xhr) { alert("Something seems Wrong"); }
});
});
});

Resources