Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET 5 / MVC 6 Ajax post Model to Controller

In my ASP.NET 5 MVC 6 application, I want to post with Ajax some data to my controller. I already done this with ASP.NET MVC 5 and I tested the exact same code in an blank ASP.NET MVC 5 project and it worked, but with the new version I can't and I don't know why. With the Ajax call, I can go to the controller, the model is created but the fields are null (or false for the boolean). Here is my code :

script.js :

var data = {             model: {                 UserName: 'Test',                 Password: 'Test',                 RememberMe: true             }         };          $.ajax({             type: "POST",             url: "/Account/Login/",             data: JSON.stringify(data),             contentType: "application/json; charset=utf-8",             dataType: "json",             success: function (msg) {                 // Do something interesting here.             }         }); 

AccountController.cs :

[HttpPost]     public JsonResult Login(LoginViewModel model)     {         if (ModelState.IsValid)         {             //var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);             //if (result.Succeeded)             //{             //     //return RedirectToLocal(returnUrl);             //}              ModelState.AddModelError("", "Identifiant ou mot de passe invalide");             return Json("error-model-wrong");         }          // If we got this far, something failed, redisplay form         return Json("error-mode-not-valid");     } 

LoginViewModel.cs :

public class LoginViewModel {     [Required]     [Display(Name = "UserName")]     [EmailAddress]     public string UserName { get; set; }      [Required]     [DataType(DataType.Password)]     [Display(Name = "Password")]     public string Password { get; set; }      [Display(Name = "Remember me?")]     public bool RememberMe { get; set; } } 

Any ideas ? Thanks

like image 798
Christophe Gigax Avatar asked Feb 28 '15 14:02

Christophe Gigax


People also ask

How pass data from Ajax to controller in ASP.NET Core?

In this article series, we will learn two methods to send the data from View to Controller using the ajax post method in the ASP.NET Core application. We will use the following methods to submit the form data in this article series: JSON Form Serialization. Without form serialization.

Can we use Ajax in MVC?

The MVC Framework contains built-in support for unobtrusive Ajax. You can use the helper methods to define your Ajax features without adding a code throughout all the views. This feature in MVC is based on the jQuery features. To enable the unobtrusive AJAX support in the MVC application, open the Web.


2 Answers

You need to explicit use FromBody on MVC6 if you are using json

public JsonResult Login([FromBody]LoginViewModel model) 

EDIT

I think you are mixing different errors. I will try to describe how you should make the request:

content-type must be: application/json

your request body must be in JSON format (as JasonLind suggested):

{     UserName: 'Test',     Password: 'Test',     RememberMe: true }; 

this is what you should see when inspecting the request (via chrome debugger tools F12) or using a request inspector like fiddler.

If you see something in the form of UserName=Test&Password=Test&RememberMe=true then you are doing it wrong, that's form format.

you don't need the model variable. if you see your request with a "wrapper" then you should remove it.

like image 72
Bart Calixto Avatar answered Sep 20 '22 10:09

Bart Calixto


You can implement BindModel yourself! get the json string and deserialize to your entity.

public class JsonBinder<T> : System.Web.Mvc.IModelBinder {     public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)     {         using (var reader = new System.IO.StreamReader(controllerContext.HttpContext.Request.InputStream))         {             //set stream position 0, maybe previous action already read the stream.             controllerContext.HttpContext.Request.InputStream.Position = 0;             string json = reader.ReadToEnd();             if (string.IsNullOrEmpty(json) == false)             {                 JavaScriptSerializer serializer = new JavaScriptSerializer();                 object jsonData = serializer.DeserializeObject(json);                 return serializer.Deserialize<T>(json);             }             else             {                 return null;             }         }     } } 

and set the JsonBinder to the post method like

[HttpPost] public JsonResult Login([ModelBinder(typeof(JsonBinder<LoginViewModel>))] LoginViewModel model) {     if (ModelState.IsValid)     {         //var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);         //if (result.Succeeded)         //{         //     //return RedirectToLocal(returnUrl);         //}          ModelState.AddModelError("", "Identifiant ou mot de passe invalide");         return Json("error-model-wrong");     }      // If we got this far, something failed, redisplay form     return Json("error-mode-not-valid"); } 

the other solution

I found that you could set DataContract to the class of Model, and set DataMember to the Properties of the class.

edit the class like this

[DataContract] public class LoginViewModel {     [DataMember]     public string UserName { get; set; }     [DataMember]     public string Password { get; set; }     [DataMember]     public bool RememberMe { get; set; } } 

and you should add library reference "System.Runtime.Serialization"

Hope it can works for u.

like image 43
oudi Avatar answered Sep 22 '22 10:09

oudi