ASP.NET LoginStatus控件 - 在生成的QueryString中覆盖ReturnURL
-
05-07-2019 - |
题
我有一个使用 ASP.NET登录控件和表单身份验证。我已将asp:LoginStatus控件放在另一个Web用户控件中,该控件管理我站点的Header部分的显示。
我遇到的问题是LoginStatus控件提供的ReturnURL引用了Header Control的路径,而不是用户当前所在的页面。这可能是由于类层次结构,并且Header Control(ascx)实际上在.aspx文件上使用Server.Execute来生成HTML。这是为了避免在页面上不允许有多个服务器端表单的问题。
因此页面的实际类层次结构如下:
Default.aspx - Uses Page.Master
Page.Master includes <foo:Header>
(with a reference to "~/Controls/Components/Header.ascx")
Header.ascx simply includes an <asp:Literal>
on Page_Load performs a Server.Execute ("~/Controls/Pages/Header.aspx")
and writes the content out to the Literal
Header.aspx includes <asp:LoginStatus>
当用户点击登录链接时,他们被正确地重定向到Login.aspx,但显示的ReturnURL(错误 - 虽然我能理解为什么)"ReturnUrl=%2fControls%2fPages%2fHeader.aspx"
。
登录页面后,我可以非常愉快地处理LoggedIn事件,以正确地将用户重定向到正确的位置。我想做的是: 1)完全从查询字符串中删除ReturnURL 2)在呈现LoginStatus控件时能够控制ReturnURL。
我已经完成了System.Web.UI.WebControls.LoginStatus的一些Reflector,看起来它是硬编码的,总是使用ReturnURL,基于以下代码:
private string NavigateUrl
{
get
{
if (!base.DesignMode)
{
return FormsAuthentication.GetLoginPage(null, true);
}
return "url";
}
}
始终将reuseReturnURL设置为true。
可能,我唯一的选择是滚动我自己的LoginStatus控件吗?
[编辑:最初为了简洁起见,我省略了以下细节]
这是我想要实现的一个非常简单的例子:
Web应用程序项目具有以下结构: 网站 - 控制 - 组件 - Footer.ascx - Header.ascx - MasterPages - Site.Master - Default.aspx - Login.aspx
如果您有兴趣,页面标记如下。
我已经创建了Web用户控件来分离关注点,但是在Login页面上使用asp:Login控件需要嵌套在(服务器端)表单中。 asp:LoginStatus控件也需要嵌套在(服务器端)表单中。由于页面上不能有多个服务器端表单,因此会中断。
此外,答案不仅仅是在Login页面上禁止LoginStatus控件。想象一下,如果我只是想在主页面上添加一个小的搜索控件,它也依赖于(服务器端)表单。因此,使用Server.Execute并从ASPX生成页面的原因。这个<!>“技巧<!>”; .NET允许在页面上使用多个服务器端表单。 (不要问我怎么......我不知道!)
也许我的整个架构设计都是错误的,但是其他人如何在需要服务器端表单的页面上拥有多个Web用户控件?或者不是吗?
Site.Master标记:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="WebSite.MasterPages.Site" %>
<%@ Register TagPrefix="bs" TagName="Footer" Src="~/Controls/Components/Footer.ascx" %>
<%@ Register TagPrefix="bs" TagName="Header" Src="~/Controls/Components/Header.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body id="Body" runat="server">
<div id="container">
<!-- start header -->
<bs:Header ID="Header" runat="server" />
<!-- end header -->
<div id="central">
<div id="main">
<asp:PlaceHolder ID="MainContentPlaceHolder" runat="server">
<!-- start main content -->
<div>
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
<!-- end main content -->
</asp:PlaceHolder>
</div>
</div>
<!-- start footer -->
<bs:Footer ID="Footer" runat="server" />
<!-- end footer -->
</div>
</body>
</html>
Default.aspx标记:
<%@ Page MasterPageFile="~/MasterPages/Site.Master" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebSite._Default" %>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="MainContent">
Main Body Content <br />
<br />
</asp:Content>
Header.ascx标记:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Header.ascx.cs" Inherits="WebSite.Controls.Components.Header" %>
<div id="header">
Header Content <br />
<div id="loginstatus">
<form id="Form1" runat="server">
<asp:LoginView ID="displayloginname" runat="server">
<AnonymousTemplate>
<a href="../../Registration.aspx">Register</a>
</AnonymousTemplate>
<LoggedInTemplate>
Welcome
<asp:LoginName runat="server" ID="ctlLoginName" />
</LoggedInTemplate>
</asp:LoginView>
<asp:LoginStatus ID="displayloginstatus" runat="server" LoginText="Login" LogoutPageUrl="~/Default.aspx"
LogoutAction="Redirect" />
</form>
<br />
</div>
</div>
Footer.ascx标记:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Footer.ascx.cs" Inherits="Website.Controls.Components.Footer" %>
<div id="footer">
Footer Content
<ul class="links">
<asp:PlaceHolder ID="ListItems" Runat="server">
<li><a runat="server" id="HomeLink" href="~/">Home</a></li>
<li><a runat="server" href="~/" ID="A1">About Us</a></li>
<li><a id="A2" runat="server" href="~/">Contact Us</a></li>
<li><a id="A3" runat="server" href="~/">Privacy Policy</a></li>
<li><a id="A4" runat="server" href="~/">Accessibility Policy</a></li>
<li><a id="A5" runat="server" href="~/">Legal Notices</a></li>
<li><a id="A6" runat="server" href="~/">Sitemap</a></li>
<li><a id="A7" runat="server" href="~/">RSS Feeds</a></li>
</asp:PlaceHolder>
</ul>
</div>
Login.aspx标记:
<%@ Page MasterPageFile="~/MasterPages/Site.Master" Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="Website.Login" %>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="MainContent">
Main Body Content <br />
<br />
<form id="form1" runat="server">
<div>
<asp:Login ID="Login1" runat="server">
</asp:Login>
</div>
</form>
</asp:Content>
解决方案
我看到两个选项:
- 将表单标记放在母版页中。就在
<div id="container"
<!> gt下面;并将所有内容包装在该div中。 - 将标题更改为不需要ASP.NET表单。不确定LoginView或LoginStatus是否都需要ASP.NET表单。然后,您可以保留使用母版页的aspx文件的表单标记(就像您在Login.aspx中一样)。我更喜欢将表单标签放在aspx页面中(而不是在主文件中),并确保页眉和页脚不需要ASP.NET表单(他们可以使用常规表单标签,而不是使用runat = server)。 醇>
其他提示
为什么要从Header.ascx执行Header.aspx的Server.Execute?为什么不把Header.aspx代码放在Header.ascx中。这样ReturnUrl将成为您期望的页面。
这里听起来不太正确:
Page_Lo上的执行Server.Execute(<!> quot;〜/ Controls / Pages / Header.aspx <!>;)
并将内容写入Literal
我不明白你为什么要这样做?您提到这是因为您试图解决ASP.NET不允许在页面上使用多个HtmlForm的问题。但是,如果您只是将header.aspx中的html内容放入文字中,那么您是不是在使用HtmlForm?那么你可以将Header.aspx的内容放在普通的表单标签中(没有runat = server)吗?或者登录状态控件是否可以完全放在表单之外? Header.aspx的内容真的需要一个表格吗?
我会好好看看你为什么要将header.aspx页面的内容写入文字并尝试解决问题,而不是潜入LoginStatus控件并更改它以执行它不打算做的事情要做。
另一个可能的建议:如果你确实需要将Header加载到文字中,你可以使用Page.LoadUserControl吗?这可能会自动为您解析网址?不过100%肯定。