wake-up-neo.net

ASP.NET 5/MVC 6 Ajax post-Modell an Controller

In meiner ASP.NET 5 MVC 6-Anwendung möchte ich mit Ajax einige Daten an meinen Controller senden. Ich habe dies bereits mit ASP.NET MVC 5 gemacht und den gleichen Code in einem leeren ASP.NET MVC 5-Projekt getestet und es hat funktioniert, aber mit der neuen Version kann ich nicht und weiß nicht warum. Mit dem Ajax-Aufruf kann ich zum Controller wechseln, das Modell wird erstellt, die Felder sind jedoch null (oder falsch für den Boolean). Hier ist mein 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; }
}

Irgendwelche Ideen? Danke

26

Sie müssen FromBody auf MVC6 explizit verwenden, wenn Sie json verwenden

public JsonResult Login([FromBody]LoginViewModel model)

EDIT

Ich denke, Sie mischen verschiedene Fehler. Ich werde versuchen zu beschreiben, wie Sie die Anfrage machen sollen:

inhaltstyp muss : application/json sein

ihr Antragstext muss im JSON-Format (wie von JasonLind vorgeschlagen) sein:

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

dies sollten Sie sehen, wenn Sie die Anforderung prüfen (über die Chrome-Debugger-Werkzeuge F12) oder einen Anforderungsinspektor wie Fiddler verwenden.

Wenn Sie etwas in der Form von UserName=Test&Password=Test&RememberMe=true sehen, machen Sie es falsch, das ist das Format des Formats.

sie brauchen die Variable model nicht. Wenn Sie Ihre Anfrage mit einem "Wrapper" sehen, sollten Sie sie entfernen.

30
Bart Calixto

Sie können BindModel selbst implementieren! Holen Sie sich den Json-String und deserialisieren Sie Ihre Entität.

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;
            }
        }
    }
}

und setzen Sie den JsonBinder auf die Post-Methode wie

[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");
}

die andere Lösung

Ich habe festgestellt, dass Sie DataContract auf die Klasse von Model und DataMember auf die Eigenschaften der Klasse setzen können.

bearbeiten Sie die Klasse so

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

und Sie sollten den Bibliotheksverweis "System.Runtime.Serialization" hinzufügen.

Hoffe es kann für dich funktionieren.

1
oudi

Ok, ich habe die Lösung gefunden, aber es ist immer noch seltsam für mich ....__ Sie müssen nur den content-type aus der Anfrage entfernen.

$.ajax({
            type: "POST",
            url: "Account/Login",
            data: data,
            success: function (msg) {
                // Do something interesting here.
            }
        });

Ich habe die Lösung dank des Beobachters gefunden :) Ich habe die Request-Variable beobachtet und fand, dass Request.Form immer eine Ausnahme warf. Es sagte, dass ich einen falschen Content-Typ verwendet habe, also habe ich gerade den content-type aus meinem Ajax-Post entfernt und es funktionierte wie ein Zauber. Ich denke, dass Sie für jeden Ajax-Beitrag, den Sie erstellen werden, darauf achten müssen, dass Ihre Request.Form richtig ausgefüllt ist

enter image description here

EDIT: Diese Lösung funktioniert nur, wenn Sie Nicht-Json-Daten (sehr einfache Daten) wie Verbindungsdaten bereitstellen könnten. Wenn ich jedoch komplexe Daten wie eine Liste posten möchte, funktioniert das nicht mehr ...

0

Ihr Problem ist nicht MVC6 ist jQuery. $ .ajax () überprüft die "Daten" und kennt das Format, so dass der Inhaltstyp für Sie festgelegt wird. Außerdem sollten Sie $ .ajax in einer vielversprechenden Weise verwenden 

versprechen prüfen hier

und auch das Formular auswählen und einfach in Objekt umwandeln, wie

 $('.anyForm').on('submit', fucntion(){
        //you have the form in JSON format
        var data = $(this).serializeObject()

    })

und hier ist die serializeObject () -Methode, sie ist standardmäßig nicht in jQuery enthalten.

Sollte es nicht sein:

 var data = {
            UserName: 'Test',
            Password: 'Test',
            RememberMe: true

    };
0
JasonLind