117 votes

Utiliser la validation ASP.NET MVC avec jquery ajax ?

J'ai une action simple ASP.NET MVC comme celle-ci :

public ActionResult Edit(EditPostViewModel data)
{

}

Le site EditPostViewModel ont des attributs de validation comme ceci :

[Display(Name = "...", Description = "...")]
[StringLength(100, MinimumLength = 3, ErrorMessage = "...")]
[Required()]
public string Title { get; set; }

Dans la vue, j'utilise les aides suivantes :

 @Html.LabelFor(Model => Model.EditPostViewModel.Title, true)

 @Html.TextBoxFor(Model => Model.EditPostViewModel.Title, 
                        new { @class = "tb1", @Style = "width:400px;" })

Si je soumets un formulaire dans lequel cette zone de texte est placée, la validation sera d'abord effectuée sur le client, puis sur le service. ModelState.IsValid ).

Maintenant, j'ai quelques questions :

  1. Peut-on l'utiliser avec jQuery ajax submit à la place ? Ce que je fais, c'est simplement supprimer le formulaire et, lorsque je clique sur le bouton "submit", un javascript recueille les données et exécute ensuite la fonction "ajax submit". $.ajax .

  2. Est-ce que le côté serveur ModelState.IsValid travail ?

  3. Comment puis-je renvoyer le problème de validation au client et le présenter comme si j'utilisais la validation int build( @Html.ValidationSummary(true) ) ?

Exemple d'appel Ajax :

function SendPost(actionPath) {
    $.ajax({
        url: actionPath,
        type: 'POST',
        dataType: 'json',
        data:
        {
            Text: $('#EditPostViewModel_Text').val(),
            Title: $('#EditPostViewModel_Title').val() 
        },
        success: function (data) {
            alert('success');
        },
        error: function () {
            alert('error');
        }
    });
}

Edit 1 :

Inclus dans la page :

<script src="/Scripts/jquery-1.7.1.min.js"></script>
<script src="/Scripts/jquery.validate.min.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js"></script>

150voto

Andrew Burgess Points 3053

Côté client

Utilisation de la jQuery.validate La bibliothèque devrait être assez simple à mettre en place.

Spécifiez les paramètres suivants dans votre Web.config fichier :

<appSettings>
    <add key="ClientValidationEnabled" value="true"/> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/> 
</appSettings>

Lorsque vous construisez votre vue, vous définissez les choses comme ceci :

@Html.LabelFor(Model => Model.EditPostViewModel.Title, true)
@Html.TextBoxFor(Model => Model.EditPostViewModel.Title, 
                                new { @class = "tb1", @Style = "width:400px;" })
@Html.ValidationMessageFor(Model => MOdel.EditPostViewModel.Title)

NOTE : Ceux-ci doivent être définis dans un élément de formulaire

Vous devez alors inclure les bibliothèques suivantes :

<script src='@Url.Content("~/Scripts/jquery.validate.js")' type='text/javascript'></script>
<script src='@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")' type='text/javascript'></script>

Cela devrait vous permettre de mettre en place la validation côté client.

Ressources

Côté serveur

NOTE : Il ne s'agit que d'une validation supplémentaire côté serveur, en plus de la validation de l'utilisateur. jQuery.validation bibliothèque

Peut-être que quelque chose comme ceci pourrait aider :

[ValidateAjax]
public JsonResult Edit(EditPostViewModel data)
{
    //Save data
    return Json(new { Success = true } );
}

ValidateAjax est un attribut défini comme :

public class ValidateAjaxAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!filterContext.HttpContext.Request.IsAjaxRequest())
            return;

        var modelState = filterContext.Controller.ViewData.ModelState;
        if (!modelState.IsValid)
        {
            var errorModel = 
                    from x in modelState.Keys
                    where modelState[x].Errors.Count > 0
                    select new
                           {
                               key = x,
                               errors = modelState[x].Errors.
                                                      Select(y => y.ErrorMessage).
                                                      ToArray()
                           };
            filterContext.Result = new JsonResult()
                                       {
                                           Data = errorModel
                                       };
            filterContext.HttpContext.Response.StatusCode = 
                                                  (int) HttpStatusCode.BadRequest;
        }
    }
}

Cette fonction renvoie un objet JSON spécifiant toutes les erreurs de votre modèle.

Un exemple de réponse serait

[{
    "key":"Name",
    "errors":["The Name field is required."]
},
{
    "key":"Description",
    "errors":["The Description field is required."]
}]

Cette information sera renvoyée à la fonction de gestion des erreurs de l'application $.ajax appelez

Vous pouvez parcourir les données renvoyées pour définir les messages d'erreur en fonction des clés renvoyées (je pense que quelque chose comme $('input[name="' + err.key + '"]') trouverait votre élément d'entrée

40voto

Shyju Points 46555

Ce que vous devez faire, c'est sérialiser les données de votre formulaire et les envoyer à l'action du contrôleur. ASP.NET MVC liera les données du formulaire à l'action du contrôleur. EditPostViewModel (paramètre de votre méthode d'action), en utilisant la fonction de liaison de modèle MVC.

Vous pouvez valider votre formulaire côté client et, si tout va bien, envoyer les données au serveur.

$(function () {
    $("#yourSubmitButtonID").click(function (e) {
        e.preventDefault();
        var _this = $(this);
        var _form = _this.closest("form");

        var validator = $("form").validate(); // obtain validator
        var anyError = false;
        _form.find("input").each(function () {
            if (!validator.element(this)) { // validate every input element inside this step
                anyError = true;
            }
        });

        if (anyError)
            return false; // exit if any error found    

        $.post(_form.attr("action"), _form.serialize(), function (data) {
             //check the result and do whatever you want
        })
    });

});

10voto

Alex Herman Points 662

Voici une solution plutôt simple :

Dans le contrôleur, nous retournons nos erreurs comme ceci :

if (!ModelState.IsValid)
        {
            return Json(new { success = false, errors = ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage).ToList() }, JsonRequestBehavior.AllowGet);
        }

Voici une partie du script du client :

function displayValidationErrors(errors)
{
    var $ul = $('div.validation-summary-valid.text-danger > ul');

    $ul.empty();
    $.each(errors, function (idx, errorMessage) {
        $ul.append('<li>' + errorMessage + '</li>');
    });
}

C'est comme ça qu'on le gère via ajax :

$.ajax({
    cache: false,
    async: true,
    type: "POST",
    url: form.attr('action'),
    data: form.serialize(),
    success: function (data) {
        var isSuccessful = (data['success']);

        if (isSuccessful) {
            $('#partial-container-steps').html(data['view']);
            initializePage();
        }
        else {
            var errors = data['errors'];

            displayValidationErrors(errors);
        }
    }
});

En outre, je rends des vues partielles via ajax de la manière suivante :

var view = this.RenderRazorViewToString(partialUrl, viewModel);
        return Json(new { success = true, view }, JsonRequestBehavior.AllowGet);

Méthode RenderRazorViewToString :

public string RenderRazorViewToString(string viewName, object model)
    {
        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
                                                                     viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View,
                                         ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }

5voto

Ajouté un peu plus de logique à la solution fournie par @Andrew Burgess. Voici la solution complète :

Création d'un filtre d'action pour obtenir les erreurs pour les requêtes ajax :

public class ValidateAjaxAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!filterContext.HttpContext.Request.IsAjaxRequest())
                return;

            var modelState = filterContext.Controller.ViewData.ModelState;
            if (!modelState.IsValid)
            {
                var errorModel =
                        from x in modelState.Keys
                        where modelState[x].Errors.Count > 0
                        select new
                        {
                            key = x,
                            errors = modelState[x].Errors.
                                                          Select(y => y.ErrorMessage).
                                                          ToArray()
                        };
                filterContext.Result = new JsonResult()
                {
                    Data = errorModel
                };
                filterContext.HttpContext.Response.StatusCode =
                                                      (int)HttpStatusCode.BadRequest;
            }
        }
    }

J'ai ajouté le filtre à la méthode de mon contrôleur comme :

[HttpPost]
// this line is important
[ValidateAjax]
public ActionResult AddUpdateData(MyModel model)
{
    return Json(new { status = (result == 1 ? true : false), message = message }, JsonRequestBehavior.AllowGet);
}

Ajout d'un script commun pour la validation jquery :

function onAjaxFormError(data) {
    var form = this;
    var errorResponse = data.responseJSON;
    $.each(errorResponse, function (index, value) {
        // Element highlight
        var element = $(form).find('#' + value.key);
        element = element[0];
        highLightError(element, 'input-validation-error');

        // Error message
        var validationMessageElement = $('span[data-valmsg-for="' + value.key + '"]');
        validationMessageElement.removeClass('field-validation-valid');
        validationMessageElement.addClass('field-validation-error');
        validationMessageElement.text(value.errors[0]);
    });
}

$.validator.setDefaults({
            ignore: [],
            highlight: highLightError,
            unhighlight: unhighlightError
        });

var highLightError = function(element, errorClass) {
    element = $(element);
    element.addClass(errorClass);
}

var unhighLightError = function(element, errorClass) {
    element = $(element);
    element.removeClass(errorClass);
}

J'ai finalement ajouté la méthode javascript d'erreur à mon formulaire Ajax Begin :

@model My.Model.MyModel
@using (Ajax.BeginForm("AddUpdateData", "Home", new AjaxOptions { HttpMethod = "POST", OnFailure="onAjaxFormError" }))
{
}

1voto

andres descalzo Points 8392

Vous pouvez le faire de cette façon :

( Edit : Considérant que vous attendez une réponse json avec dataType: 'json' )

.NET

public JsonResult Edit(EditPostViewModel data)
{
    if(ModelState.IsValid) 
    {
       // Save  
       return Json(new { Ok = true } );
    }

    return Json(new { Ok = false } );
}

JS :

success: function (data) {
    if (data.Ok) {
      alert('success');
    }
    else {
      alert('problem');
    }
},

Si vous avez besoin, je peux aussi vous expliquer comment faire en retournant une erreur 500, et obtenir l'erreur dans l'événement d'erreur (ajax). Mais dans votre cas, cela peut être une option

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X