2009-10-09 7 views
6

Il y a une abondance de très bon poste et des explications comment mettre en œuvre la validation avec ASP.NET MVC, et je préfère l'un de ces:

Cependant, j'aime vraiment appeler ActionMethods via la méthode jquery $ .ajax. L'une des raisons pour lesquelles je veux utiliser $ .ajax est qu'il y aura beaucoup de vues partielles chargées dynamiquement dans la page (même le formulaire de création d'entité) via les appels $ .ajax et je ne peux pas simplement retourner la vue - Je vais perdre tout le contenu chargé dynamiquement. Pour vous donner une meilleure vue sur le problème, je vais poster un code simple pour expliquer comment je voudrais appeler les actions des contrôleurs et gérer les réponses dans le client, le code de jQuery.

Les contrôleurs ActionMethod:

public ActionResult CreateCustomer(string name, string accountNumber) 
    { 
     try 
     { 
      CustomerService.InsertCustomer(name, accountNumber); 

      return Json(new ActionInfo() 
      { 
       Success = true, 
       Message = "Customer Is Successfully Created" 
      }); 

     } 
     catch (Exception ex) 
     { 
      return Json(new ActionInfo() 
      { 
       Success = false, 
       Message = ex.Message 
      }); 
     } 
    } 

appel et la manipulation dans le code client:

$.ajax({ 
type: "POST", 
url: $form.attr('action'),// /MyController/CreateCustomer 
data: $form.serialize(), 
error: HandleUnespectedError, 
dataType: "json", 
success: function(response) { 

    if (response.Success) 
     alert("Success: " + response.Message); 
    else 
     alert("Error: " + response.Message); 
}}); 

est-il un bon moyen de faire certains de ces cadres de validation pour travailler la façon dont je besoin? Je sais que je peux ajouter des erreurs de validation dans ActionInfo, puis le gérer dans le client, mais ce serait déjà la construction de ma seule validation, je crois.

Répondre

5

J'ai eu beaucoup de succès en validant via AJAX en utilisant des attributs d'annotations de données. Pour vérifier la validité de vos données, vous devez utiliser la propriété ModelState du contrôleur, qui possède sa propre propriété appelée IsValid. Je suggère fortement de jeter un coup d'œil au data annotations validation attributes tutorial sur le site officiel d'ASP.NET MVC. Tout d'abord, vous devrez modifier l'action de votre contrôleur pour accepter votre objet modèle en tant que paramètre, plutôt qu'un nom et un numéro de compte distincts. Cela rendra la validation, que je vais démontrer ci-dessous, beaucoup plus simple. De votre exemple, ma meilleure estimation est que votre objet de modèle est, ou serait, appelé Client. Vous pourriez avoir le code suivant pour définir l'objet modèle et votre action de contrôleur ...

// model object 
public class Customer 
{ 
    public Int32 Id {get; set;} 
    public String Name {get; set;} 
    public String AccountNumber {get; set;} 
} 

// controller 
public class CustomerController : Controller 
{ 
    public ActionResult CreateCustomer([Bind(Exclude = "Id")] Customer customer) 
    { 
    // controller action code 
    } 
} 


Assurez-vous que vos champs de formulaire sont nommés pour faire correspondre les noms des propriétés de l'objet client afin ASP .NET MVC peut les lier automagiquement. L'attribut "Bind", dans ce cas, indique à ASP.NET MVC d'ignorer la propriété "Id" de la classe Customer lors de la liaison des champs de formulaire aux propriétés du modèle. Comme il s'agit d'un nouveau client, nous n'avons pas encore d'identifiant. Nous pouvons donc laisser l'identifiant en toute sécurité, quelle que soit la valeur par défaut, et laisser la couche de données déterminer la meilleure façon de la générer.

Une fois que le contrôleur a construit l'objet de modèle pour la méthode d'action, sa validité peut être facilement vérifiée via la propriété ModelState.IsValid. Comme on peut s'y attendre, il retournera vrai si les propriétés du modèle sont valides, ou faux si 1 ou plusieurs propriétés ne sont pas valides.

De la question d'origine, il semble que la méthode CustomerService.InsertCustomer lève des exceptions lorsque la validation échoue.Ceci est complètement inutile. InsertCustomer ne doit effectuer que les opérations de données nécessaires à l'insertion du nouvel enregistrement. À moins que vous souhaitiez abstraire des exceptions spécifiques à l'implémentation, comme SqlException, InsertCustomer ne devrait pas vraiment avoir besoin d'intercepter ou de lancer des exceptions, mais peut très probablement laisser toute exception surgir au contrôleur (ou à l'appelant).

Le résultat final tout cela, peut-être une action de contrôleur qui ressemble à ce qui suit:

public ActionResult CreateCustomer([Bind(Exclude = "Id")] Customer customer) 
{ 
    // model is invalid 
    if (!ModelState.IsValid) 
    { 
    return Json(new ActionInfo() 
    { 
     Success = false, 
     Message = "Validation failed" // you will probably want a more robust message :-) 
    }); 
    } 

    // service method accepts a Customer object rather than arbitrary strings 
    CustomerService.InsertCustomer(customer); 

    return Json(new ActionInfo() 
    { 
    Success = true, 
    Message = "Customer created successfully." 
    }); 

} 


Si vous voulez signaler des erreurs inattendues, comme des exceptions liées à la base de données, vous peut certainement ajouter un bloc try/catch autour de l'appel à InsertCustomer, et retourner le résultat nécessaire pour afficher le message d'erreur au client.

+0

Salut thedude! Merci beaucoup pour l'effort :) Je suis entièrement d'accord avec vous pour l'entité Client pour la liaison (voulait faire comme ça, je ne sais pas pourquoi avais-je mis la méthode avec des paramètres simples) et pour la gestion des exceptions à coup sûr. Avec xVal, je peux facilement implémenter la validation du client, et si quelqu'un l'évite, je l'attraperai en action. Mais comment pourrais-je présenter des messages de validation à côté des champs dans ce cas? –

+0

Pour cela, vous souhaitez renvoyer une vue partielle plutôt que JSON à partir de votre action de contrôleur. Dans votre vue partielle, vous utiliseriez la méthode d'assistance Html.ValidationMessage() pour afficher un message d'erreur pour chaque champ. Les messages d'erreur de niveau champ générés par vos attributs Data Annotations sont disponibles pour votre contrôleur via la propriété ModelState. Par exemple, pour obtenir le premier message d'erreur pour un champ appelé name, vous l'obtiendrez via ModelState ["Name"]. Errors [0] .ErrorMessage'. Jetez également un coup d'œil à la méthode 'Ajax.BeginForm'. Je l'ai utilisé avec beaucoup de succès dans le passé. –

+1

C'est ce que j'ai réalisé, soit je vais retourner JSON vue partielle, et c'est ce que je n'aime pas ... Cependant, je vais jeter un coup d'oeil comment faire avec MS construit dans les fonctionnalités Ajax, bien que mon souhait était d'éviter cela :) Merci –

2

Cela fait plus d'un an après que vous ayez posé votre question, mais j'ai couvert la validation côté serveur avec des appels Ajax dans mon blog post qui pourraient vous intéresser beaucoup. Je vois que vous renvoyez des résultats échoués en tant qu'appels HTTP réussis. J'ai traité ceci différemment (je suppose que c'est plus correct puisque $.ajax a la capacité de la fonctionnalité de réponse success et error). Et votre exemple particulier est un exemple parfait qui pourrait être implémenté avec la fonctionnalité que j'explique dans mon article de blog. Fondamentalement, au lieu de toujours renvoyer une réponse réussie (mais avec des propriétés définies pour indiquer au client que le traitement côté serveur a échoué), je lance plutôt une exécution sur le serveur et la gère en conséquence sur le client. J'utilise une classe ModelStateException personnalisée avec un filtre d'action HandleModelStateException.

Questions connexes