2009-04-17 8 views
4

Je cite l'exemple d'application ASP.NET MVC NerdDinnerMVC - Conditions dans les vues

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> 
<% 
    if (Request.IsAuthenticated) { 
%> 
     Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>! 
     [ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ] 
<% 
    } 
    else { 
%> 
     [ <%= Html.ActionLink("Log On", "LogOn", "Account") %> ] 
<% 
    } 
%> 

Ceci est de la vue partielle usercontrol nommé LoginStatus.ascx. Comme vous pouvez le voir, il existe une condition qui modifie la sortie 'entière' de la vue. C'est la bonne route. Aurait-il été préférable qu'il y ait un contrôleur évaluant cette condition et rendant la vue partielle appropriée? Et quelle que soit votre réponse à la question précédente, Comment puis-je adopter cette dernière approche dans ASP.NET MVC, c'est-à-dire qu'une vue parente peut appeler un contrôleur (au lieu de faire un RenderPartial de UserControl) et laisser décider quelle partie vue à rendre?

+0

@Ngu Soon Hui: Merci –

Répondre

4

Comment cette approche:

Solution 1:

Créer une méthode d'extension sur HtmlHelper qui rend si vue "WelcomeMessage.Anonymous.aspx" ou "WelcomeMessage.Authenticated.aspx" basé sur la demande.

<%= Html.LoginStatus() => 

Et mettre ces vues sous/Vues/Partagé

/Views/Shared/LoginStatus.Anonymous.ascx 
/Views/Shared/LoginStatus.Authenticated.ascx 

Solution 2:

Il suffit de remplacer if/else déclarations avec contrôle ASP.NET LoginView dans votre LoginStatus.ascx

<asp:LoginView Runat="Server"> 
    <LoggiedInTemplate> 
     Welcome, <%= Html.Encode(Model.UserName) %>! 
     <button>Sign Out</button> 
    </LoggedInTemplate> 
    <AnonymousTemplate> 
     <button>Sign In</button> | <button>Join Now!</button> 
    </AnonymousTemplate> 
</asp:LoginView> 

Voir aussi:

+0

@Koistya Navin .NET: Bon pour un hack mais la question est toujours là. Est-ce que je ne peux pas prendre la deuxième approche que j'ai décrite avec ASP.NET MVC? –

1

Je pense que si la vue va changer en fonction de certaines conditions, il est de la responsabilité de la vue de l'appliquer. Mais si la condition change, non l'apparence (ie "les nombres négatifs doivent être rouges") mais le comportement (si "l'utilisateur est connecté il doit voir le bouton LOGOUT au lieu du bouton LOGIN") alors c'est au contrôleur de décider . Vous pourriez introduire un niveau de "rendu" entre le contrôleur et la page.

+0

Je suis plutôt d'accord avec votre raisonnement mais pas avec votre exemple. Le bouton est la responsabilité d'une vue. Souhaitez-vous alors également laisser un contrôleur décider quelle vue afficher si c'est impression/non impression? Je laisserais un fichier css faire ça. –

+0

Puisque le bouton permet à l'utilisateur de faire quelque chose (connexion, par exemple) que vous pourriez ne pas vouloir faire si elle est déjà connecté, vous devez encore écrire la logique pour l'empêcher d'invoquer l'URL "http: // mysite .org/login? username = mickey & password = goofy "(juste un exemple ... :) - donc c'est différent de" print/dontprint "qui est quelque chose que vous pouvez facilement décider en fonction du média que vous utilisez. –

0

Je pense que ce que vous faites est tout à fait Allright. De telles petites choses comme des changements dans l'affichage pourraient et devraient être entreprises par des vues.

Par exemple, j'ai un menu principal rendu par un ascx séparé. Il y a beaucoup de telles petites vérifications à l'intérieur afin de décider quel texte afficher et quels styles appliquer aux éléments de la liste. S'il y a de grandes décisions à prendre en pensant à la vue à afficher en fonction de l'action de l'utilisateur, le contrôleur interroge la logique métier et décide de la vue sur laquelle renvoyer l'URL à rediriger. Mais s'il s'agit d'un élément d'interface utilisateur assez stable où seules les options de texte et de couleur sont légèrement modifiées, mettez-y la logique nécessaire.

Vous pouvez également transmettre un modèle séparé à votre ascx avec plusieurs drapeaux définissant quoi et comment devrait être affiché. Ensuite, la logique actuelle pour définir ces indicateurs sera ailleurs sur le niveau de la logique métier et tout ce que votre vue va faire est de regarder ces drapeaux et de les restituer en conséquence.

Ne vous inquiétez pas, vous le faites correctement.

+0

@Mastermind: Eh bien, j'ai cité cet exemple pour plus de brièveté, mais cette question peut facilement correspondre à un scénario plus large. Même ici, la condition détermine non seulement l'apparence de la sortie mais également la fonctionnalité, c'est-à-dire que l'utilisateur doit être autorisé à se connecter ou à se déconnecter. –

+0

Si ces deux vues diffèrent uniquement cosmétiquement comme si elles avaient des couleurs différentes et de petits changements comme du texte authentifié/non authentifié, alors il est possible de l'avoir dans un seul contrôle. Si ces vues sont vraiment différentes, comme la vue utilisateur et la vue administrateur, il s'agit maintenant de deux vues différentes et elles doivent être implémentées séparément. – User

0

Au lieu de décider si l'utilisateur est authentifié dans la vue, vous pouvez le faire dans le contrôleur, comme ceci:

public ActionResult ShowAPage() 
{ 
    if(!HttpContext.User.Identity.IsAuthenticated) 
    { 
     return RedirectToRoute("ShowLoginPage") 
    } 
    return View(); 
} 

Ensuite, vous pouvez rediriger vers une page de connexion plutôt que d'avoir cette logique dans une vue , ce qui n'est pas vraiment une séparation des préoccupations.

Une façon vraiment géniale de faire cela est d'utiliser une page maître différente pour les utilisateurs authentifiés que pour les utilisateurs non authentifiés. Je suppose que vous voulez toujours afficher une connexion, ou déconnecter le lien, de cette façon vous pouvez utiliser un filtre ActionFilter pour changer la page maître en fonction de l'authentification de l'utilisateur. Ensuite, vos utilisateurs connectés peuvent obtenir des choses comme des barres de navigation que vous voudriez peut-être cacher aux étrangers, sans que vous ayez à vous prononcer sur la logique d'affichage.

Voici une façon de le faire sans utiliser un filtre d'action, mais vous pouvez faire toutes sortes de choses, une bonne consiste à créer un contrôleur personnalisé qui hérite du contrôleur et remplace les méthodes View pour sélectionner la page maître appropriée.

public ActionResult ShowAPage() 
{ 
    if(!HttpContext.User.Identity.IsAuthenticated) 
    { 
     return View("ShowAPageView", "LoggedInMasterPageName"); 
    } 
    return View("ShowAPageView", "LoggedOutMasterPageName");  
} 

Espérons que cela aide.

Questions connexes