Domanda

Ho un sito Web che utilizza i Controlli di accesso ASP.NET e autenticazione moduli. Ho inserito il controllo asp: LoginStatus all'interno di un altro controllo utente Web che gestisce la visualizzazione della parte Header del mio sito.

Il problema che ho è che ReturnURL presentato dal controllo LoginStatus fa riferimento al percorso del controllo Header, non alla pagina in cui si trova l'utente. Ciò è probabilmente dovuto alla gerarchia di classi e che il controllo dell'intestazione (ascx) utilizza effettivamente Server.Execute su un file .aspx per generare l'HTML. Questa è una soluzione per evitare il problema di non poter avere più di un modulo sul lato server in una pagina.

Quindi la Gerarchia di classe effettiva della Pagina è la seguente:

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>

Quando l'utente fa clic sul collegamento Accesso, viene reindirizzato correttamente a Login.aspx, tuttavia ReturnURL visualizzato viene (erroneamente - anche se posso capire perché) "ReturnUrl=%2fControls%2fPages%2fHeader.aspx".

Una volta nella pagina di accesso, posso tranquillamente gestire l'evento LoggedIn per reindirizzare correttamente l'utente nel posto giusto. Quello che vorrei fare è: 1) Rimuovere ReturnURL dalla stringa di query del tutto 2) Essere in grado di controllare ReturnURL quando viene eseguito il rendering del controllo LoginStatus.

Ho fatto un po 'di riflessione su System.Web.UI.WebControls.LoginStatus e sembra che sia codificato per usare sempre un ReturnURL, basato sul seguente codice:

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

Imposta sempre reuseReturnURL su true.

Forse, la mia unica scelta è quella di ottenere il mio controllo LoginStatus?

[EDIT: originariamente per brevità, ho omesso i seguenti dettagli]

Ecco un esempio davvero semplice di ciò che sto cercando di ottenere:

Il progetto di applicazione Web ha la seguente struttura: Sito web  - Controlli    - Componenti      - Footer.ascx      - Header.ascx  - MasterPages    - Site.Master  - Default.aspx  - Login.aspx

I markup delle pagine sono di seguito se sei interessato.

Ho creato il controllo utente Web per la separazione delle preoccupazioni, tuttavia nella pagina di accesso per utilizzare asp: i controlli di accesso devono essere nidificati in un modulo (lato server). L'asp: anche il controllo LoginStatus deve essere nidificato in un modulo (lato server). Poiché non è possibile avere più di un modulo sul lato server in una pagina, questo si interrompe.

Inoltre, la risposta non è solo quella di sopprimere il controllo LoginStatus nella pagina Login. Immagina se volessi solo aggiungere un po 'di controllo di ricerca sulla pagina principale, che farebbe affidamento anche su un modulo (lato server). Da qui il motivo per l'utilizzo di un Server. Eseguire e generare una pagina da un ASPX. Questo & Quot; inganna & Quot; .NET nel consentire più moduli lato server su una pagina. (Non chiedermi come ... non lo so!)

Forse la mia intera architettura non è corretta, ma come possono avere altri controlli utente Web su una pagina che richiede moduli sul lato server? O no?

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

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

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

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

Markup 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>
È stato utile?

Soluzione

Vedo due opzioni:

  1. Inserisci il tag del modulo nella tua pagina principale. Appena sotto il <div id="container" & Gt; e racchiudendo tutto il contenuto in quella div.
  2. Modifica l'intestazione per non richiedere un modulo ASP.NET. Non sono sicuro se LoginView o LoginStatus richiedono entrambi un modulo ASP.NET. E quindi puoi lasciare il tag del modulo per i file aspx che usano la pagina principale (come hai fatto in Login.aspx). Questo è ciò che preferisco è inserire i tag del modulo solo nelle pagine aspx (non nei file master) e assicurarsi che le intestazioni e il piè di pagina non abbiano bisogno di un modulo ASP.NET (potrebbero usare un tag del modulo normale ma non con runat = server).

Altri suggerimenti

Perché esegui un Server.Execute di Header.aspx dal tuo Header.ascx? Perché non inserisci semplicemente il codice Header.aspx in Header.ascx. In questo modo ReturnUrl sarà la pagina che ti aspetti che sia.

Qualcosa non suona proprio qui:

  

su Page_Load esegue un Server.Execute (" ~ / Controls / Pages / Header.aspx ")
  e scrive il contenuto in Letterale

Non capisco perché lo stai facendo? Dici che è perché stai cercando di aggirare il problema di ASP.NET non consentendo più di un HtmlForm su una pagina. Ma se stai semplicemente mettendo i contenuti html da header.aspx in un letterale, allora non stai usando un HtmlForm ?? Quindi puoi semplicemente mettere il contenuto di Header.aspx in un normale tag di modulo (senza runat = server)? O il controllo dello stato di accesso può essere messo completamente al di fuori del modulo? I contenuti di Header.aspx hanno davvero bisogno di un modulo in primo luogo?

Vorrei dare una buona occhiata al motivo per cui stai scrivendo i contenuti della tua pagina header.aspx su un valore letterale e provo a risolvere il problema lì invece di immergerti nel controllo LoginStatus e cambiarlo per fare qualcosa che non è previsto da fare.

Un altro possibile suggerimento: se devi davvero caricare Header in un valore letterale, puoi usare Page.LoadUserControl? Questo potrebbe risolvere automaticamente gli URL per te? Non sicuro al 100% però.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top