Элемент управления ASP.NET LoginStatus - переопределение ReturnURL в сгенерированном QueryString
-
05-07-2019 - |
Вопрос
У меня есть веб-сайт, который использует элементы управления входом ASP.NET Аутентификация по формам. Я поместил элемент управления asp: LoginStatus в другой элемент управления веб-пользователя, который управляет отображением заголовочной части моего сайта. Р>
У меня проблема в том, что ReturnURL, представленный элементом управления LoginStatus, ссылается на путь к элементу управления заголовком, а не на страницу, на которой в данный момент находится пользователь. Вероятно, это связано с иерархией классов и тем, что элемент управления заголовком (ascx) фактически использует Server.Execute в файле .aspx для генерации 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) Уметь управлять ReturnURL при визуализации элемента управления LoginStatus.
Я сделал несколько рефлекторов System.Web.UI.WebControls.LoginStatus, и кажется, что он всегда жестко запрограммирован на ReturnURL на основе следующего кода:
private string NavigateUrl
{
get
{
if (!base.DesignMode)
{
return FormsAuthentication.GetLoginPage(null, true);
}
return "url";
}
}
Он всегда устанавливает для reuseReturnURL значение true.
Возможно, мой единственный выбор - развернуть свой собственный элемент управления LoginStatus?
[РЕДАКТИРОВАТЬ: Первоначально ради краткости я пропустил следующие детали]
Вот очень простой пример того, что я пытаюсь достичь:
Проект веб-приложения имеет следующую структуру: Веб-сайт - Управление - Компоненты - Footer.ascx - Header.ascx - MasterPages - Site.Master - Default.aspx - Login.aspx
Разметки страницы ниже, если вам интересно.
Я создал пользовательский веб-элемент управления для разделения задач, однако на странице входа в систему для использования элементов управления asp: Login они должны быть вложены в (на стороне сервера) форму. Элемент управления asp: LoginStatus также должен быть вложен в (на стороне сервера) форму. Поскольку на странице не может быть более одной серверной формы, это нарушается.
Кроме того, ответ заключается не только в подавлении элемента управления LoginStatus на странице входа в систему. Представьте себе, если бы я просто хотел добавить небольшой элемент управления поиском на главной странице, который также опирался бы на форму (на стороне сервера). Отсюда и причина использования Server.Execute и создания страницы из ASPX. Этот & Трюк & Quot; .NET в разрешении нескольких серверных форм на странице. (Не спрашивайте меня, как ... я не знаю!)
Может быть, весь мой архитектурный дизайн неправильный, но как другим иметь несколько веб-элементов управления на странице, которые требуют серверных форм? Или нет?
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. Другие советы
Почему вы делаете Server.Execute из Header.aspx из вашего Header.ascx? Почему бы вам просто не поместить код Header.aspx в Header.ascx. Таким образом, ReturnUrl будет той страницей, на которой вы ожидаете.
Что-то здесь звучит не совсем правильно:
в Page_Load выполняет Server.Execute (" ~ / Controls / Pages / Header.aspx ")
и записывает содержимое в литерал
Я не понимаю, зачем ты это делаешь? Вы упоминаете, что это потому, что вы пытаетесь обойти проблему ASP.NET, не позволяющую использовать более одной HtmlForm на странице. Но если вы просто помещаете html-содержимое из header.aspx в литерал, тогда вы не используете HtmlForm ?? Так что вы можете просто поместить содержимое Header.aspx в обычный тег формы (без runat = server)? Или можно полностью контролировать состояние входа в систему за пределы формы? Действительно ли содержимое Header.aspx действительно нуждается в форме? Р>
Я бы хорошо посмотрел, почему вы записываете содержимое своей страницы header.aspx в литерал, и попытался бы устранить проблему вместо того, чтобы погрузиться в элемент управления LoginStatus и изменить его, чтобы он выполнял что-то, для чего он не предназначен делать.
Еще одно возможное предложение: если вам действительно нужно загрузить Header в литерал, можете ли вы использовать Page.LoadUserControl вместо этого? Это может автоматически разрешить URL для вас? Хотя не уверен на 100%.