Pregunta

Tengo un sitio web que utiliza los Controles de inicio de sesión ASP.NET y Autenticación de formularios. He colocado el control asp: LoginStatus dentro de otro control de usuario web que gestiona la visualización de la parte de encabezado de mi sitio.

El problema que tengo es que el ReturnURL presentado por el control LoginStatus hace referencia a la ruta al Control de encabezado, no a la página en la que se encuentra actualmente el usuario. Esto probablemente se deba a la jerarquía de clases y a que el Control de encabezado (ascx) en realidad usa Server.Execute en un archivo .aspx para generar el HTML. Esta es una solución alternativa para evitar el problema de no poder tener más de un formulario del lado del servidor en una página.

Entonces la Jerarquía de clase real de la Página es la siguiente:

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>

Cuando el usuario hace clic en el enlace Iniciar sesión, se le redirige correctamente a Login.aspx, sin embargo, se muestra el ReturnURL (incorrectamente, aunque puedo entender por qué) "ReturnUrl=%2fControls%2fPages%2fHeader.aspx".

Una vez en la página de inicio de sesión, puedo manejar el evento LoggedIn para redirigir correctamente al usuario al lugar correcto. Lo que me gustaría hacer es: 1) Elimine el ReturnURL de la cadena de consulta por completo 2) Poder controlar el ReturnURL cuando se registre el Control LoginStatus.

He hecho algunos Reflectores del System.Web.UI.WebControls.LoginStatus y parece que está codificado para usar siempre un ReturnURL, basado en el siguiente código:

private string NavigateUrl
{
    get
    {
        if (!base.DesignMode)
        {
            return FormsAuthentication.GetLoginPage(null, true);
        }
        return "url";
    }
}

Siempre establece reuseReturnURL en verdadero.

¿Posiblemente, mi única opción es rodar mi propio control LoginStatus?

[EDITAR: originalmente por razones de brevedad, omití los siguientes detalles]

Aquí hay un ejemplo muy simple de lo que estoy tratando de lograr:

Web Application Project tiene la siguiente estructura: Sitio web  - Controles    - componentes      - Footer.ascx      - Header.ascx  - MasterPages    - Site.Master  - Default.aspx  - Login.aspx

Las marcas de página están debajo si está interesado.

He creado el Control de usuario web para separar las preocupaciones, sin embargo, en la página de inicio de sesión para usar asp: los controles de inicio de sesión deben anidarse en un formulario (del lado del servidor). El control asp: LoginStatus también debe estar anidado en un formulario (del lado del servidor). Como no puede tener más de un formulario del lado del servidor en una página, esto se rompe.

Además, la respuesta no es solo suprimir el control LoginStatus en la página de inicio de sesión. Imagínese si solo quisiera agregar un poco de Control de búsqueda en la página principal, que también dependería de un formulario (del lado del servidor). De ahí la razón para usar un servidor. Ejecutar y generar una página desde un ASPX. Este & Quot; trucos & Quot; .NET para permitir múltiples formularios del lado del servidor en una página. (No me preguntes cómo ... ¡No lo sé!)

Tal vez el diseño de toda mi arquitectura es incorrecto, pero ¿cómo otros tienen múltiples controles de usuario web en una página que requiere formularios del lado del servidor? ¿O no?

Site.Master markup:

<%@ 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>

Marcado de 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>

Marcado de 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>

Marcado 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>

Marcado de 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>
¿Fue útil?

Solución

Veo dos opciones:

  1. Ponga su etiqueta de formulario en su página maestra. Justo debajo de <div id="container" & Gt; y envolviendo todo el contenido en ese div.
  2. Cambie su encabezado para no requerir un formulario ASP.NET. No estoy seguro si LoginView o LoginStatus requieren un formulario ASP.NET. Y luego puede dejar la etiqueta de formulario para los archivos aspx que usan la página maestra (como la que tiene en Login.aspx). Esto es lo que prefiero es poner solo etiquetas de formulario en páginas aspx (no en archivos maestros) y asegurarme de que los encabezados y pies de página no necesiten un formulario ASP.NET (podrían usar una etiqueta de formulario normal, pero no con runat = server).

Otros consejos

¿Por qué haces un Server.Execute del Header.aspx de tu Header.ascx? ¿Por qué no pones el código Header.aspx en Header.ascx? De esa manera, ReturnUrl será la página que espera que sea.

Algo no suena bien aquí:

  

en Page_Load realiza un Server.Execute (" ~ / Controls / Pages / Header.aspx ")
  y escribe el contenido en Literal

No entiendo por qué estás haciendo esto. Usted menciona que se debe a que está tratando de solucionar el problema de que ASP.NET no permite más de un HtmlForm en una página. Pero si solo está poniendo el contenido html de header.aspx en un literal, ¿entonces no está usando un HtmlForm? Entonces, ¿puede simplemente poner el contenido de Header.aspx en una etiqueta de forma normal (sin runat = server)? ¿O el control de estado de inicio de sesión se puede colocar completamente fuera del formulario? ¿El contenido de Header.aspx realmente necesita un formulario en primer lugar?

Me gustaría ver por qué está escribiendo el contenido de su página header.aspx en un literal y tratar de solucionar el problema allí en lugar de sumergirse en el control LoginStatus y cambiarlo para hacer algo que no está destinado hacer.

Otra sugerencia posible: si realmente necesita cargar el encabezado en un literal, ¿puede usar Page.LoadUserControl en su lugar? Esto puede resolver automáticamente las URL por usted? Aunque no estoy 100% seguro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top