0

Je demande cela parce que après une longue période de recherche que je ne l'ai pas trouvé une bonne réponse sur ce encore ...ASP.NET validation complexe dans la couche d'affaires/services

Voici ce que je veux:

Exemple: J'ai un modèle de domaine "JobPosting" qu'un utilisateur devrait pouvoir changer d'état à publié, s'il s'agit toujours d'un brouillon. Avant de publier, je dois non seulement valider les propriétés du modèle, mais également valider de nombreuses exigences différentes concernant le compte d'utilisateur, sa société enregistrée, etc. Toute cette logique de validation est placée dans une couche de service. Jusqu'à présent, si bon ...

Voici comment ma couche de service ressemble à:

public IValidationResult ValidatePublish(JobPosting jobPosting){ 
    ... 
} 

public void Publish(JobPosting jobPosting){ 
    jobPosting.State = JobPostingState.Published; 
    ... 
} 

Tout mon contrôleur:

public ActionResult Publish(PublishViewModel model){ 
    ... 
    var validationResult = _jobService.ValidatePublish(jobPosting); 
    if(validationResult.Success){ 
     _jobService.Publish(jobPosting); 
     ... 
    } 
    ... 
} 

Et voici maintenant mes questions:

Je veux pour pouvoir appeler le ValidatePublish à partir du contrôleur pour afficher les erreurs de validation dans la vue. Cependant, je ne dois jamais être capable de publier un travail lorsque la validation échoue. Donc, pour avoir mon code plus robuste j'ai ajouté une deuxième vérification de validation dans mon Publier méthode dans la couche de service:

public void Publish(JobPosting jobPosting){ 
    if(ValidatePublish(jobPosting).Success){ 
     jobPosting.State = JobPostingState.Published; 
     ... 
    } 
} 

mais je n'ai pas un bon feeling avec cette approche parce que maintenant je fais appel à la validation à deux reprises lors de la validation est OK lors de chaque demande de publication de contrôleur.

Que pensez-vous. Est-ce que le deuxième appel à beaucoup? Est-ce qu'il y a une meilleure approche? Je demande parce que mon application entière ressemble à cela et si jamais j'oublierais un appel de validation dans le contrôleur je pourrais finir avec un état de modèle de domaine non autorisé dans la base de données. C'est pourquoi j'ai ajouté la deuxième vérification de validation dans chaque méthode de service.

Merci d'avance pour vos commentaires à ce sujet !!!

+0

"J'appelle la validation deux fois" où appelez-vous la validation une deuxième fois? –

+0

Premier appel dans le contrôleur: var validationResult = _jobService.ValidatePublish (jobPosting); Deuxième fois dans la méthode de service Publier: if (ValidatePublish (jobPosting) .Success) { – Simon

+0

alors pourquoi validez-vous à nouveau dans la méthode? Vous pouvez simplement publier directement. –

Répondre

1

Une solution rapide pourrait être que la classe Publisher requière les objets JobPosting et IValidationResult comme arguments.

public void Publish(JobPosting jobPosting, IValidationResult validation) 
{ 
    if (validation.IsValid) 
    { 
     jobPosting.State = JobPostingState.Published; 
     // other work here... 
    } 
} 

Votre Controller peut alors appeler le Validator, recevoir un IValidationResult et de transmettre ce message à la couche de présentation si nécessaire. Sinon, passer à Publisher

public ActionResult Publish(PublishViewModel model) 
{ 
    var validationResult = _jobService.ValidatePublish(jobPosting); 
    if(validationResult.Success) _jobService.Publish(jobPosting, validationResult); 
    else return View("error", validationResult); 
} 

Edit:

Une solution plus propre peut être d'avoir la classe Publisher retourner un résultat PublishAttempt.

public class PublishAttempt : IValidationResult 
{ 
    public enum AttemptOutcome {get; set;} 
} 

public ActionResult Publish(PublishViewModel model) 
{ 
    var attempt = _jobService.Publish(jobPosting); 
    if (attempt.Success) return View("success"); 
    else return View("error", attempt.ValidationResults); 
} 
+0

Merci! Oui, ce serait aussi une approche ... mais ce que je n'aime pas, c'est que je pourrais passer n'importe quelle instance de résultat de validation ... je pourrais même en créer une nouvelle vide qui est toujours valide. – Simon

+0

Oh merci :-) oui j'aime ça ... peut-être que je combine votre idée avec ma dernière réponse :-) juste parce que j'ai besoin de la capacité de l'appel seulement la méthode de validation ... par exemple. quand je veux appeler le service de validation via ajax pour montrer les erreurs en "temps réel" – Simon

-1

Ce qui suit vient de me venir à l'esprit ...Que pensez-vous:

je change ma méthode de service:

public IValidationResult Publish(JobPosting jobPosting, bool validateOnly = false){ 
    var validationResult = ValidatePublish(jobPosting); 
    if(validateOnly) return validationResult; 

    jobPosting.State = JobPostingState.Published; 
    ... 
    return validationResult; 
}   

Et puis dans le contrôleur, je fais toujours appel que la publication méthode et non la ValidatePublish supplémentaire plus:

public ActionResult Publish(PublishViewModel model) 
{ 
    var validationResult = _jobService.Publish(jobPosting); 
    if(!validationResult.Success) return View("error", validationResult); 
} 

Et quand Je n'ai besoin que de la simple validation que je fais

var validationResult = _jobService.Publish(jobPosting, true); 

Est-ce normal de le faire comme ça? Ou n'est-ce pas beau si un appel de service normal renvoie IValidationResult?

+0

Ou pensez-vous qu'il est préférable d'implémenter une sorte de résultat par méthode de service? – Simon