IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ASP.NET MVC Discussion :

annotation dans le model pour tester l'unicité d'une valeur


Sujet :

ASP.NET MVC

  1. #1
    Futur Membre du Club
    Femme Profil pro
    Inscrit en
    Mars 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme

    Informations forums :
    Inscription : Mars 2013
    Messages : 7
    Points : 7
    Points
    7
    Par défaut annotation dans le model pour tester l'unicité d'une valeur
    Bonjour,
    J'ai des classes Models. Certaines valeurs doivent être uniques lors de l'insertion dans la base. Est ce qu'il y a une annotation en MVC4 qui assure ce teste?

    J'ai trouvé ceci sur internet; mais apparemment ça ne marche pas pour MVC4, il n'y a pas l'annotation Remote:
    [Remote("columnNameAvailable", "Users")]
    public string columnName{ get; set; }

    Merci d'avance.

  2. #2
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2013
    Messages : 39
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par mannou87 Voir le message
    Bonjour,
    J'ai des classes Models. Certaines valeurs doivent être uniques lors de l'insertion dans la base. Est ce qu'il y a une annotation en MVC4 qui assure ce teste?

    J'ai trouvé ceci sur internet; mais apparemment ça ne marche pas pour MVC4, il n'y a pas l'annotation Remote:
    [Remote("columnNameAvailable", "Users")]
    public string columnName{ get; set; }

    Merci d'avance.
    Non, a juste raison ça ne "marche pas" en MVC, parce que c'est le travail du contrôleur, inconnu en ASP. Voici un petit exemple de la vérification de ce que le nom d'utilisateur et le mot de passe n'existent pas dans la base, lors de l'enregistrement d'un nouvel utilisateur sur un site:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
            [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public ActionResult Register(RegisterModel model)
            {
                if (ModelState.IsValid) //TODO Change this to use a worker to send emails.
                {
                    // Check if email exists already before creating new user
                    using (UsersContext db = new UsersContext())
                    {
                        UserProfile email = db.UserProfiles.FirstOrDefault(u => u.Email.ToLower() == model.Email.ToLower());
                        UserProfile uName =
                            db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());
     
                        // Attempt to register the user
                        try
                        {
                            if (email == null && uName == null && this.IsCaptchaVerify("Captcha is not valid"))
                            {
                                bool requireEmailConfirmation = !WebMail.SmtpServer.IsEmpty();
                                string confirmationToken = WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new
                                {
                                    FirstName = model.FirstName,
                                    LastName = model.LastName,
                                    Email = model.Email                               
                                },
                                requireEmailConfirmation);
                                if (requireEmailConfirmation)
                                {
                                    EmailViewModel eml = new EmailViewModel
                                                             {
                                                                 ToEmail = model.Email,
                                                                 Subject = "Confirmez votre inscription",
                                                                 FirstName = model.FirstName,
                                                                 LastName = model.LastName,
                                                                 Body = confirmationToken
                                                             };
     
                                    UserMailer.ConfirmRegistration(eml).SendAsync();
     
                                    Response.Redirect("~/Account/Thanks");                            
                                }
                                else
                                {
                                    WebSecurity.Login(model.UserName, model.Password);
                                    Response.Redirect("~/");
                                }                           
                            }
                            else
                            {
                                if (email != null)
                                    ModelState.AddModelError("Email", "Email address already exists. Please enter a different email address.");
     
                                if (uName != null)
                                    ModelState.AddModelError("UserName", "User Name already exists. Please enter a different user name.");
     
                                if (!this.IsCaptchaVerify("Captcha is not valid"))
                                    TempData["ErrorMessage"] = "Captcha is not valid";
                            }
     
                        }
                        catch (MembershipCreateUserException e)
                        {
                            ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                        }
                    }
                }
     
                // If we got this far, something failed, redisplay form
                return View(model);
            }
    ce qu'il faut noter d'interessant dans ce code, c'est que les données ne sont pas effacées du model, qui est retourné avec la vue en cas d'erreur. L'utilisateur n'a donc pas à ressaisir, juste à corriger les erreurs. De plus on peut ajuster finement les erreurs retournées à l'utilisateur.

    Les annotations dans le modèle, qui existent aussi, sont montrées à l'utilisateur sans besoin de retour vers le serveur, directement par du javascript, donc coté client, alors que ce genre d'erreurs, qui nécessitent une vérification coté base de données, ne peuvent être faites que par une aller-retour client/serveur.

  3. #3
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2013
    Messages : 76
    Points : 143
    Points
    143
    Par défaut
    C'est possible de le faire, mais il faudra créer pour ça un nouvel attribut qui vérifiera si cette valeur du champs existe déjà. Il faudra aussi créer la clé Unique en base de donnée.
    Tu peux retrouver quelques explications ici : http://stackoverflow.com/questions/5...-ef-code-first

    L'utilisation du Remote sert pour la validation distante : msdn.microsoft.com/fr-fr/library/gg508808(v=vs.98).aspx

    A tu biens une méthode "columnNameAvailable" dans ton contrôleurs "Users"?

  4. #4
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2013
    Messages : 39
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par g.Arnaud Voir le message
    C'est possible de le faire, mais il faudra créer pour ça un nouvel attribut qui vérifiera si cette valeur du champs existe déjà. Il faudra aussi créer la clé Unique en base de donnée.
    Tu peux retrouver quelques explications ici : http://stackoverflow.com/questions/5...-ef-code-first

    L'utilisation du Remote sert pour la validation distante : msdn.microsoft.com/fr-fr/library/gg508808(v=vs.98).aspx

    A tu biens une méthode "columnNameAvailable" dans ton contrôleurs "Users"?
    Je pense qu'il y a une petite confusion: Les explications citées concernent la création de clefs unique en code first, de manière à ce que lorsque la base est générée, elle comporte les clefs uniques souhaitées, ce que EF CodeFirst ne fait pas par défaut, sauf pour les clefs primaires. Il ne s'agit PAS de validation de saisie, qui comme je l'indiquais ne peut pas se faire coté client, mais coté serveur.

    Je peux me tromper, bien sûr, mais je ne vois pas trés bien comment détecter l'entrée de doublons sans un aller-retour entre la méthode du controlleur qui reçoit le HTTPPost, et la base de données.

    L'annotation remote est du "syntaxic sugar" (qui peut s'avérer trés utile) qui "cache" l'aller retour dont je parlais par un appel Ajax vers le controleur, généré depuis le model par cet attribut. Ce genre de facilités d'écriture peuvent rendre de grands services, mais il me semble qu'il ne faut surtout pas qu'elles masquent les principes et les différences entre ce qui est purement coté client et ce qui nécessite l'utilisation de méthodes du serveur.

  5. #5
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2013
    Messages : 76
    Points : 143
    Points
    143
    Par défaut
    Il me semble avoir vu sur le lien que j'ai passer un post qui expliquait les différentes étapes:

    Création de l'attribut
    Utilisation de l'attribut
    Création de la contrainte en bdd (C'est le genre de contrainte qu'il est bien d'avoir aussi en bdd en cas d'entrée manuel)


    Il me semble pas qu'une validation sans aller-retour était demandée, non?
    Je pense pas non plus avoir dit que la validation pourrait se faire sans aller-retour au serveur.

    Après pour moi, les annotations ne sont pas là uniquement pour faire les validations par javascript. La validation se fera aussi niveau serveur.
    Les annotations peuvent aussi être utiliser sans asp.net MVC.

    Par contre l'annotation "Remote" est propre à asp.net MVC et se trouve donc dans le namespace "system.web.mvc".
    Oui Remote fera bien un aller-retour vers le serveur, mais ceci avant que le formulaire soit soumis. L'utilisateur voit donc ses erreurs au plus tôt.

  6. #6
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2013
    Messages : 39
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par g.Arnaud Voir le message
    Après pour moi, les annotations ne sont pas là uniquement pour faire les validations par javascript. La validation se fera aussi niveau serveur.
    C'est justement ce point que je cherchais à éclaircir du mieux possible: NON, la plupart des annotations "standards" (en tous cas en MVC) ne se font pas coté serveur, mais uniquement coté client. Par exemple, la vérification de l'entrée d'une zone email valide, où de la longueur mini et maxi d'une chaine de caractère, n'ont aucun besoin de passer par le serveur.

    Les annotations peuvent aussi être utilisées sans asp.net MVC.
    Je ne connais pas suffisamment ASP.NET (tout court), mais je connais assez bien EntityFramework, effectivement, certaines annotation ne sont destinées qu'à EntityFramework et à la génération par CodeFirst de la base de données. XAML utilise aussi ces annotations, pour la validation, de la même manière qu'Asp

    Par contre l'annotation "Remote" est propre à asp.net MVC et se trouve donc dans le namespace "system.web.mvc".
    Oui Remote fera bien un aller-retour vers le serveur, mais ceci avant que le formulaire soit soumis. L'utilisateur voit donc ses erreurs au plus tôt.
    Effectivement, et c'est une trés bonne chose.

    Au risque de me répéter, il me semble important de faire clairement la différence entre les contrôles de saisie qui ne nécessitent pas une vérification à partir des données existantes dans la base (tout ce qui concerne le "masque" de saisie), longueur d'une chaine, uniquement numeros où lettres, format d'une adresse email, etc, etc, qui se font donc uniquement coté client, et celles qui vont nécessiter une requête sur la base et donc un passage par le serveur.

    Une bonne raison pour faire cette différence étant que les premières a priori existent d'office dans la boite à outils MVC, les secondes pas nécessairement.

  7. #7
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2013
    Messages : 76
    Points : 143
    Points
    143
    Par défaut
    Citation Envoyé par BernieG Voir le message
    C'est justement ce point que je cherchais à éclaircir du mieux possible: NON, la plupart des annotations "standards" (en tous cas en MVC) ne se font pas coté serveur, mais uniquement coté client.
    Je vais me permettre de te contredire sur ce point. La validation ne se fait en aucun cas uniquement du côté client. Fais le test en désactivant Javascript.

    Il m'est aussi arriver d'avoir la validation coté client et coté serveur qui n'arrivait pas à se mettre d'accord. L'un considérait "." comment séparateur de décimal et l'autre ",", j'avais donc dans tout les cas une erreur de validation pour un nombre avec une partie décimale.

    Il serait dangereux de n'avoir de validation que par le client, javascript peut être désactiver et on peut aussi se passer de navigateur web pour envoyer des requêtes HTTP (ex: fiddler)

  8. #8
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2013
    Messages : 39
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par g.Arnaud Voir le message
    Je vais me permettre de te contredire sur ce point. La validation ne se fait en aucun cas uniquement du côté client. Fais le test en désactivant Javascript.
    Rien à voir. Le javascript, dans ce cas, n'est pas de l'ajax, et ne sert qu'à l'affichage de la validation, c'est à dire les messages d'erreurs. Sans javascript, alors, et alors seulement, la validation se fait coté serveur, PARCEQU'ELLE N'A PAS PU ETRE FAITE COTE CLIENT. Elle ne se fait pas des 2 cotés en même temps!

    C'est pas trés compliqué à vérifer: Par défaut lorsqu'un formulaire de saisie est créé en scaffolding par MVC, ces lignes sont ajoutées au bas de la forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    @section Scripts {
    	@Scripts.Render("~/bundles/jqueryval")
    }
    dans jqueryval, il y a 2 fichiers:
    • jquery.validate.js
    • jquery.unobtrusive-ajax.js


    jquery.validate.js est celui qui est utilisé pour faire la validation coté client, et va permettre l'affichage d'erreurs zone par zone, AVANT de valider/envoyer la totalité du formulaire au serveur. AUCUN AJAX DEDANS;

    jquery.unobtrusive-ajax répond uniquement et exclusivement aux événements $(document).on('click') et/où on('submit'). Autrement dit, aucune validation à a la volée zone par zone; mais uniquement lors de l'envoi du formulaire lui-même (à l'ancienne, si je puis dire).

    Tout cela me semble parfaitement bien expliqué ici: http://www.asp.net/mvc/tutorials/mvc...n-to-the-model

    Pas trés compliqué à vérifier: il suffit de mettre un point d'arrêt sur la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (ModelState.IsValid)
    d'une méthode avec HttpPost. Si le formulaire est bati sur un modèle, comme celui-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class ContactModel
        {        
            [Required]
            [Display(Name = "Your name")]
            public string UserName { get; set; }        
     
            [RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",
                ErrorMessage = "Please enter a valid e-mail adress")]
            [Required]
            [DataType(DataType.EmailAddress)]
            [Display(Name = "Email address")]
            public string Email { get; set; }
     
            [Required]
            [Display(Name = "Subject")]
            public string Subject { get; set; }
     
            [Required]   
            [DataType(DataType.MultilineText)]
            [Display(Name = "Text")]
            public string Text{ get; set; }       
        }
    ou il n'y a aucun controle de saisie lié à une base de données (pour la bonne raison qu'il n'y en a pas!), le point d'arrêt ne sera jamais atteint avant l'appui sur le bouton qui valide l'envoi du formulaire tant que javascript est utilisé par le browser, même si toutes les zones sont en erreur. Si on invalide l'utilisation de javascript par le navigateur, alors, oui, le point d'arret sera atteint AVANT que l'erreur ne soit signalée à l'utilisateur. Je viens de faire ce test....

    Pour ce qui est de l'erreur de validation avec la décimale, entre point et virgule, la solution est donnée dans le même article déjà cité:

    "Note to support jQuery validation for non-English locales that use a comma (",") for a decimal point, you must include globalize.js and your specific cultures/globalize.cultures.js file(from https://github.com/jquery/globalize ) and JavaScript to use Globalize.parseFloat. The following code shows the modifications to the Views\Movies\Edit.cshtml file to work with the "fr-FR" culture:"

    Tout ce qui précède renforce et expose clairement ce que je disais dans un message précédent: il est important de distinguer et de savoir ce qui se passe coté client, coté serveur, et les raisons et le pourquoi des allers et retours lorsqu'ils sont nécessaires, sachant que, suivant la charge du serveur, pouvoir se passer de lui et régler certains problèmes uniquement coté client vous vaudra sa reconnaissance éternelle (du serveur..)

    ps- pour ce qui est des petits malins utilisant Fiddler pour envoyer des données, je ne vois pas trés bien comment cela pourrait passer le test if (ModelState.Isvalid) ????

  9. #9
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2013
    Messages : 76
    Points : 143
    Points
    143
    Par défaut
    Citation Envoyé par BernieG Voir le message
    Pour ce qui est de l'erreur de validation avec la décimale, entre point et virgule, la solution est donnée dans le même article déjà cité:
    Merci, je connaissais déjà la solution. C'était un cas permettant justement de voir la double validation, par le client ET par le serveur. Vu que les 2 validaient différemment, on avait toujours une valeur invalide, une fois à cause du javascript et l'autre fois à cause du serveur.


    Citation Envoyé par BernieG Voir le message
    ps- pour ce qui est des petits malins utilisant Fiddler pour envoyer des données, je ne vois pas trés bien comment cela pourrait passer le test if (ModelState.Isvalid) ????
    Une requête HTTP est une requête HTTP qu'elle soit envoyé par un navigateur ou par un autre outil. Pour passer le test if (ModelState.Isvalid), il suffit de formater sa requête HTTP de façon à ce que les valeurs soient valides.

    S'il y a besoin de plus pour te convaincre qu'il y a toujours une validation au niveau du serveur et ce même s'il y a une validation côté client. Essaye en utilisant un outils qui te permet de modifier une requête HTTP à la volée en mettant une valeur non valide dans un des champs.

    J'ai relu le lien que tu as mis. à aucune moment il ne dit qu'il n'y a pas de validation coté serveur si la validation est faite par JavaScript. Il dit clairement que les données ne sont pas envoyé au serveur si la validation JavaScript détecte des erreurs. Ce qui ne veut pas dire "Le serveur ne fait pas de vérification si la validation JavaScript n'as pas détecter d'erreur".

    S'il faut, on peut continuer à en parler en mp vu que là on sort quand même pas mal des questions posées dans le post initial

  10. #10
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2013
    Messages : 39
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par g.Arnaud Voir le message
    Merci, je connaissais déjà la solution. C'était un cas permettant justement de voir la double validation, par le client ET par le serveur. Vu que les 2 validaient différemment, on avait toujours une valeur invalide, une fois à cause du javascript et l'autre fois à cause du serveur.



    Une requête HTTP est une requête HTTP qu'elle soit envoyé par un navigateur ou par un autre outil. Pour passer le test if (ModelState.Isvalid), il suffit de formater sa requête HTTP de façon à ce que les valeurs soient valides.

    S'il y a besoin de plus pour te convaincre qu'il y a toujours une validation au niveau du serveur et ce même s'il y a une validation côté client. Essaye en utilisant un outils qui te permet de modifier une requête HTTP à la volée en mettant une valeur non valide dans un des champs.

    J'ai relu le lien que tu as mis. à aucune moment il ne dit qu'il n'y a pas de validation coté serveur si la validation est faite par JavaScript. Il dit clairement que les données ne sont pas envoyé au serveur si la validation JavaScript détecte des erreurs. Ce qui ne veut pas dire "Le serveur ne fait pas de vérification si la validation JavaScript n'as pas détecter d'erreur".

    S'il faut, on peut continuer à en parler en mp vu que là on sort quand même pas mal des questions posées dans le post initial
    Si tu veux, mais je crois surtout que cette discussion repose sur une petite incompréhension de ce que je cherche à dire: il me semble que tu parles de la validation en général, alors que je parle de la validation "à la volée", zone par zone.

    Message envoyé en MP pour certaines précisions qui, effectivement, débordent le cadre de la question originale.

Discussions similaires

  1. Réponses: 5
    Dernier message: 28/03/2012, 17h04
  2. Réponses: 1
    Dernier message: 06/10/2009, 10h06
  3. Réponses: 2
    Dernier message: 09/08/2007, 11h08
  4. Réponses: 2
    Dernier message: 06/06/2007, 16h27
  5. Fonction pour tester l'existence d'une image
    Par nais_ dans le forum Langage
    Réponses: 4
    Dernier message: 10/09/2006, 11h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo