MVC - 在视图
条件从的NerdDinner ASP.NET MVC范例应用程序MVC - 在视图
<%@ 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") %> ]
<%
}
%>
这是命名为LoginStatus.ascx局部视图用户控件引用。正如你所看到的那样,存在改变视图的“整个”输出的条件。这是正确的方法。如果控制器评估这种情况,然后渲染适当的局部视图,会不会更好?
不管你对上一个问题的回答如何在ASP.NET MVC中采用后一种方法,即父视图可以调用控制器(而不是执行UserControl的RenderPartial),并让它决定哪个部分视图呈现?
如何对这种做法:
解决方案1 :
创建于HtmlHelper
扩展方法,这将使得无论是 “WelcomeMessage.Anonymous.aspx” 或 “WelcomeMessage.Authenticated.aspx” 视图基于请求。下/浏览/分享
/Views/Shared/LoginStatus.Anonymous.ascx
/Views/Shared/LoginStatus.Authenticated.ascx
解决方案2
<%= Html.LoginStatus() =>
并把这些意见:
只需更换if/else
陈述与ASP.NET的LoginView控制在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>
也参见:
@Koistya Navin .NET:很好的黑客,但问题依然存在。我能不采取我用ASP.NET MVC描述的第二种方法吗? – 2009-04-17 08:11:17
我认为如果视图会因此而改变,那么视图的责任就是强制执行此操作。但是如果条件改变而不是外观(即“负数应该是红色的”)而是行为(即“如果用户登录他/他必须看到注销按钮而不是登录按钮”),那么它是控制器的决定。您可能会在控制器和页面之间引入“渲染器”级别。
我倾向于赞同你的推理,但不是你的榜样。按钮是视图的责任。那么你还会让控制器决定是否打印/不打印要显示的视图?我会让一个CSS文件做到这一点。 – 2009-04-17 08:06:52
由于该按钮允许用户执行某些操作(例如,登录),如果她已经记录了,您可能不希望她执行任何操作,您仍然必须编写逻辑来阻止她调用URL“http:// mysite .org/login?username = mickey&password = goofy“(只是一个例子... :) - 所以这与”print/dontprint“不同,根据您使用的媒体,这可能很容易决定。 – 2009-04-17 08:52:46
我觉得你在做什么是非常好吧。诸如展示变化之类的小事情可以并且应该由观点来进行。
例如,我有一个由单独的ascx呈现的主菜单。里面有很多这样的小检查来决定要显示哪些文本以及哪些样式适用于列表元素。
如果有很大的决定像基于某些用户操作考虑渲染哪个视图那么控制器会询问业务逻辑并决定返回哪个视图以重定向到哪里。但是,如果它是一个相当稳定的UI元素,只有文本和颜色选项稍有改变,那么就把必要的逻辑加入其中。
您还可以将一个单独的模型传递给您的ascx,并使用几个标志来定义显示内容和显示方式。然后,设置这些标志的实际逻辑将位于业务逻辑层的其他位置,并且您的所有视图都会查看这些标志并进行相应的渲染。
别担心,你做得对。
相反,如果用户在查看认证决定的,你能做到在控制器中,像这样:
public ActionResult ShowAPage()
{
if(!HttpContext.User.Identity.IsAuthenticated)
{
return RedirectToRoute("ShowLoginPage")
}
return View();
}
然后你就可以重定向到登录页面,而不是在一个视图中有这样的逻辑,这不是真正的问题分离。
这样做的一个非常酷的方式是为认证用户使用不同的母版页,而不是未经认证的用户。我认为你要始终显示登录或注销链接,这样你可以使用ActionFilter根据用户的认证来更改主页面。然后,您登录的用户可以获得像导航栏那样的内容,您可能想要从外部隐藏,而无需在显示逻辑中进行确定。
这里有一种不使用动作过滤器的方法,但可以采用各种方法,一个好的方法是创建一个自定义控制器,该控制器从控制器继承并覆盖View方法以选择适当的母版页。
public ActionResult ShowAPage()
{
if(!HttpContext.User.Identity.IsAuthenticated)
{
return View("ShowAPageView", "LoggedInMasterPageName");
}
return View("ShowAPageView", "LoggedOutMasterPageName");
}
希望这会有所帮助。
@Ngu Soon Hui:谢谢 – 2009-04-17 07:51:51