2009-06-17 4 views
0

У меня есть сайт, который использует ASP.NET Login Controls и Forms Authentication. Я разместил элемент управления asp: LoginStatus в другом веб-элементе управления пользователями, который управляет отображением части заголовка моего сайта.ASP.NET LoginStatus Control - переопределение ReturnURL в сгенерированном QueryString

Проблема, которую я имею, заключается в том, что ReturnURL, представленный элементом управления LoginStatus, ссылается на путь к элементу управления заголовком, а не на странице, на которой пользователь в данный момент включен. Вероятно, это связано с иерархией классов и что Header Control (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?

[EDIT: Первоначально для краткости, я опустил следующие детали]

Вот очень простой пример того, что я пытаюсь для того чтобы достигнуть:

Project

Web Application имеет следующую структуру: WebSite - Управление - Компоненты - Footer.ascx - Header.ascx - MasterPages - Site.Master - Default.aspx - Login.aspx

Наклейки на страницы ниже, если вам интересно.

Я создал элемент управления веб-пользователями для разделения проблем, однако на странице входа в систему, чтобы использовать элементы управления asp: Login, они должны быть вложены в (на стороне сервера). Элемент управления asp: LoginStatus также должен быть вложен в (на стороне сервера). Поскольку на странице не может быть больше одной серверной формы, это прерывается.

Кроме того, ответ заключается не только в подавлении элемента управления LoginStatus на странице входа. Представьте, если бы я просто хотел добавить небольшой элемент управления поиском на главной странице, который также будет опираться на (серверную) форму. Отсюда причина использования Server.Execute и создание страницы из ASPX. Это «трюки» .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> 

ответ

0

Я вижу два варианта:

  1. Поместите свой тэг формы в вашей главной странице. Только ниже <div id="container"> и обертывание всего содержимого этого div.
  2. Измените заголовок, чтобы он не требовал формы ASP.NET. Не уверен, что для входа в LoginView или LoginStatus требуется форма ASP.NET. А затем вы можете оставить тег формы для файлов aspx, которые используют главную страницу (например, у вас есть в Login.aspx). Это то, что я предпочитаю, - это только добавлять теги формы в aspx-страницы (а не в главные файлы) и следить за тем, чтобы заголовки и нижние колонтитулы не нуждались в форме ASP.NET (они могли бы использовать обычный тег формы, а не только с runat = server).
+0

Спасибо за предложения, Джефф, я отдам их. – plancake

0

Почему вы делаете Server.Execute в Header.aspx от вашего Header.ascx? Почему бы вам просто не поместить код Header.aspx в Header.ascx. Таким образом, ReturnUrl будет страницей, которую вы ожидаете.

0

Что-то не звучит достаточно прямо здесь:

на Page_Load выполняет Server.Execute ("~/Органы управления/Страницы/Header.aspx")
и записывает содержимое из буквального

Я не понимаю, почему вы это делаете? Вы упомянули, что это связано с тем, что вы пытаетесь обойти проблему ASP.NET, не позволяя на странице больше одного HtmlForm. Но если вы просто помещаете содержимое html из header.aspx в литерал, тогда вы не используете HtmlForm ?? Так можете ли вы просто поместить содержимое Header.aspx в тег нормальной формы (без runat = server)? Или может ли элемент управления статусом входа быть вне формы полностью? В самом деле, содержимое Header.aspx действительно нуждается в форме?

Я бы хорошо рассмотрел, почему вы пишете содержимое своей страницы header.aspx в литеральном виде и пытаетесь исправить проблему там вместо того, чтобы нырять в элемент управления LoginStatus и изменить его, чтобы что-то сделать предназначенный для этого.

Еще одно возможное предположение: если вам действительно нужно сделать загрузку заголовка в литерал, вы можете использовать Page.LoadUserControl вместо этого? Это может автоматически разрешить ваши URL-адреса? Тем не менее, не 100%.

+0

Я отредактирую свой вопрос, чтобы предоставить немного больше информации ... – plancake

+0

В ответ на ваши вопросы ... 1) asp: Элемент управления LoginStatus требует формы на стороне сервера, поэтому да, мой заголовок (элемент управления или страница) не имеет значения, для чего требуется форма на стороне сервера. 2) asp: для входа в систему требуется также серверная форма. Возможно, именно здесь моя проблема заключается в том, как я могу использовать два веб-элемента управления пользователями на одной странице, для которых требуются серверные формы? – plancake

Смежные вопросы