2017-06-06 2 views
2

Je travaille sur un site Web et j'essaie simplement de comprendre la structure générale. J'ai une base de données en arrière-plan que j'accède en utilisant le "Repository Pattern". J'ai le code ci-dessous dans mon UserRepository Classe:Modèle de référentiel - Objet de validation et message de retour

public bool IsValid(User user) 
{ 
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress)) 
    { 
    Message = "Email address already in use"; 
    return false; 
    } 

    return true; 
} 

Et qui est mis en œuvre ici

[HttpPost] 
[AllowAnonymous] 
[ValidateAntiForgeryToken] 
public ActionResult Register(User user) 
{ 
    if (ModelState.IsValid) 
    { 
    var context = new Context("DatabaseContext"); 
    var userRepo = new UserRepository(context); 

    if (userRepo.IsValid(user)) 
    { 
     userRepo.Add(user); 
     // return to different view 
    } 
    else 
    { 
     // display userRepo.Message on page 
     return View(user); 
    } 
    } 

    return View(user); 
} 

Mon problème est que je ne pense pas que je vais dans le bit « message » correctement , mais je ne trouve rien en ligne pour m'aider (en particulier autour du référentiel). Je pense Je devrais changer le type de retour de IsValid à quelque chose comme un résultat (comme je l'ai vu avec les boîtes de dialogue), mais encore une fois, je ne suis pas sûr.

Toute aide serait grandement appréciée.

Merci.

+0

À l'heure actuelle, vous avez un critère de validation, donc un booléen aurait du sens. Si les choses deviennent beaucoup plus compliquées, pensez à renvoyer le message (une chaîne) sur une erreur, puis vérifiez si elle est nulle (en cas de succès). Ou si nécessaire, vous pouvez aller aussi loin que ce que le ModelState fait dans le contrôleur. – robjam

Répondre

2

Une façon d'y parvenir est exactement comme vous avez suggéré - changer le type de retour de IsValid. Par le passé, j'ai eu des méthodes de validation similaires dans ma "couche de gestion" qui renvoient une collection de ValidationResult, où chaque enregistrement retourné représente une erreur de validation dans le modèle et une collection vide serait interprétée comme un modèle valide.

Par exemple:

public class ValidationResult 
{ 
    public string FieldName { get; set; } 
    public string Message { get; set; } 
} 

public interface IValidator<T> 
{ 
    IEnumerable<ValidationResult> IsValid(T model); 
} 

//...in your implementation 
public IEnumerable<ValidationResult> IsValid(User user) 
{ 
    //Return a new ValidationResult per validation error 
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress)) 
    { 
     yield return new ValidationResult 
     { 
      Message = "Email address already in use", 
      FieldName = nameof(user.EmailAddress) 
     }; 
    } 
} 

Cela pourrait alors être interprété par votre couche de présentation à la rétroaction à l'utilisateur.

+1

Merci pour ça. Non seulement vous m'avez donné une bonne solution, mais vous m'avez aidé à comprendre comment fonctionne le rendement. – Oyyou

+0

@oyyou s'il vous plaît vérifier ma réponse. Peut être que cela vous aidera à comprendre plus. – Rajput

2

Je suis d'accord avec ce que vous avez mentionné en question. Le retour de la classe personnalisée sera mieux l'approche de l'OMI.

public ValidationResult IsValid(User user) 
{ 
    ValidationResult validationResult = new ValidationResult(true, ""); 
    if (_context.Users.Any(c => c.EmailAddress == user.EmailAddress)) 
    { 
    validationResult.Status = false; 
    validationResult.Message = "Email address already in use"; 
    return validationResult; 
    } 

    return validationResult; 
} 

De cette façon, Status et Message vous donner toutes les informations nécessaires. Vérifiez l'état en premier. Si c'est faux, vérifiez le message pour les détails exacts.

+0

J'aime ça. C'est facile à comprendre et à implémenter. Je vais à la réponse de Mark Oliver car elle va donner un moyen d'expansion; mais c'est toujours valide. Merci! – Oyyou

1

Bien que la solution fournie par l'utilisateur ci-dessus soit bonne, mais je ne pense pas que vous le fassiez correctement. Ce type de solution d'adresse e-mail de validation a quelques inconvénients. Supposons que si l'email est disponible (non valide car ce n'est pas la validité), vous devez retourner la vue avec une erreur. Et si toute l'adresse email d'entrée est disponible, l'utilisateur recevra cette erreur plusieurs fois mais la vue entière sera rendu dans chaque demande et ce n'est pas une bonne pratique. Essayez toujours d'utiliser la validation à distance dans ce genre de scénario.

Utilisez Remoteattribute sur les propriétés de votre modèle (e-mail) et essayez de renvoyer dynamiquement le message de disponibilité dans la vue via JsonResult. Je vous donne cet exemple de démonstration, n'hésitez pas à implémenter dans votre code.

[OutputCache(Location = OutputCacheLocation.None, NoStore = true)] 
public JsonResult IsEmailAvailable(string emailAddress) 
{ 
    if (!_context.Users.Any(c => c.EmailAddress == emailAddress)) 
    { 
     return Json(true, JsonRequestBehavior.AllowGet); 
    } 
    return Json("Email address already taken" , JsonRequestBehavior.AllowGet); 
} 

L'attribut OutputCacheAttribute est nécessaire afin d'éviter la mise en cache de ASP.NET MVC les résultats des méthodes de validation.

et décorer votre modèle Email propriété comme ceci:

//inside you model. 
    [Required] 
    [Remote("IsEmailAvailable", "YourControllerName")] 
    [RegularExpression(@"Your email address validation regex here", ErrorMessage = "Email address is not valid .")] 
    [Editable(true)] 
    public string Email{ get; set; } 

Et ajouter cet extrait dans le fichier web.config pour permettre l'utilisation de l'attribut à distance:

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

et supprimer le code ci-dessous à partir de register méthode d'action.

if (userRepo.IsValid(user)) 
    { 
     userRepo.Add(user); //write this only inside code cause you will always get valid email now. 
     // return to different view 
    } 
    else 
    { 
     // display userRepo.Message on page 
     return View(user); 
    } 

J'espère que cela fonctionnera. Pour plus d'informations, veuillez lire cet article. https://msdn.microsoft.com/en-us/library/gg508808(vs.98).aspx

+0

La validation côté client est une bonne * addition *. Vous avez toujours besoin de la validation du serveur pour les demandes malveillantes/erronées. – Oliver

+0

Ceci fournit une validation côté serveur. où j'ai mentionné la validation côté client. @ Oliver – Rajput

+0

Il y a presque toujours une validation qui est basée sur des règles métier, par exemple une adresse email ne peut pas être dupliquée entre 2 utilisateurs. C'est pourquoi une méthode de validation au niveau de l'entreprise est une bonne option en plus de la validation du client/niveau de présentation. – Oliver