Question

Mon site Web utilise les contrôles de connexion ASP.NET et l'authentification par formulaires. J'ai placé le contrôle asp: LoginStatus dans un autre contrôle d'utilisateur Web qui gère l'affichage de la partie En-tête de mon site.

Le problème que j'ai est que l'URL ReturnURL présenté par le contrôle LoginStatus fait référence au chemin d'accès au contrôle d'en-tête, et non à la page sur laquelle l'utilisateur se trouve actuellement. Ceci est probablement dû à la hiérarchie des classes et au fait que le contrôle d'en-tête (ascx) utilise en fait Server.Execute sur un fichier .aspx pour générer le code HTML. Ceci est une solution pour éviter le problème de ne pas être autorisé à avoir plusieurs formulaires côté serveur sur une page.

La hiérarchie de classe de la page est donc la suivante:

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>

Lorsque l'utilisateur clique sur le lien de connexion, il est correctement redirigé vers Login.aspx. Cependant, ReturnURL affiché est (incorrectement - bien que je puisse comprendre pourquoi) "ReturnUrl=%2fControls%2fPages%2fHeader.aspx".

Une fois sur la page de connexion, je peux très bien gérer l'événement LoggedIn pour rediriger correctement l'utilisateur au bon endroit. Ce que je voudrais faire est soit: 1) Supprimer complètement le ReturnURL de la chaîne de requête 2) Être capable de contrôler ReturnURL lorsque le contrôle LoginStatus est rendu.

J'ai effectué quelques réflexions sur System.Web.UI.WebControls.LoginStatus et il semble qu'il soit codé en dur de toujours utiliser un ReturnURL, basé sur le code suivant:

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

Il définit toujours reuseReturnURL sur true.

Peut-être que mon seul choix est de lancer mon propre contrôle LoginStatus?

[EDIT: À l’origine par souci de brièveté, j’ai omis les détails suivants]

Voici un exemple très simple de ce que j'essaie de réaliser:

Le projet d'application Web a la structure suivante: Site Internet  - Les contrôles    - Composants      - Footer.ascx      - Header.ascx  - MasterPages    - Site.Master  - Default.aspx  - Login.aspx

Les annotations de page sont en dessous si cela vous intéresse.

J'ai créé le contrôle utilisateur Web pour la séparation des problèmes. Toutefois, sur la page de connexion, les contrôles asp: Login doivent être imbriqués dans un formulaire (côté serveur). Le contrôle asp: LoginStatus doit également être imbriqué dans un formulaire (côté serveur). Comme vous ne pouvez pas avoir plus d’un formulaire côté serveur sur une page, cela se brise.

En outre, la solution ne consiste pas uniquement à supprimer le contrôle LoginStatus sur la page de connexion. Imaginez si je voulais juste ajouter un petit contrôle de recherche sur la page principale, qui reposerait également sur un formulaire (côté serveur). D'où la raison d'utiliser Server.Execute et de générer une page à partir d'un ASPX. Cette & Quot; astuces & Quot; .NET en permettant plusieurs formulaires côté serveur sur une page. (Ne me demandez pas comment… je ne sais pas!)

Peut-être que toute ma conception d'architecture est fausse, mais comment les autres utilisateurs peuvent-ils avoir plusieurs contrôles utilisateur Web sur une page nécessitant des formulaires côté serveur? Ou n'est-ce pas?

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

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

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

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

Balisage 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>
Était-ce utile?

La solution

Je vois deux options:

  1. Placez votre balise de formulaire dans votre page maître. Juste en dessous de <div id="container" & Gt; et envelopper tout le contenu dans cette div.
  2. Modifiez votre en-tête pour ne pas requérir de formulaire ASP.NET. Vous ne savez pas si LoginView ou LoginStatus nécessitent tous deux un formulaire ASP.NET. Et vous pouvez ensuite laisser la balise de formulaire pour les fichiers aspx qui utilisent la page maître (comme dans Login.aspx). C’est ce que je préfère: ne mettre que les balises de formulaire dans les pages aspx (pas dans les fichiers maîtres) et s’assurer que les en-têtes et les pieds de page n’ont pas besoin d’un formulaire ASP.NET (ils pourraient utiliser une balise de formulaire standard, mais pas avec runat = server).

Autres conseils

Pourquoi faites-vous une Server.Execute du Header.aspx à partir de votre Header.ascx? Pourquoi ne pas simplement mettre le code Header.aspx dans Header.ascx. De cette façon, ReturnUrl sera la page que vous attendez.

Quelque chose ne sonne pas très bien ici:

  

sur Page_Load effectue un Server.Execute (" ~ / Controls / Pages / Header.aspx ")

  et écrit le contenu au Littéral

Je ne comprends pas pourquoi vous faites cela? Vous dites que c'est parce que vous essayez de contourner le problème d'ASP.NET qui n'autorise pas plus d'un formulaire HTML sur une page. Mais si vous ne faites que mettre le contenu html de header.aspx dans un littéral, vous n’utilisez pas de fichier HtmlForm? Alors pouvez-vous simplement mettre le contenu de Header.aspx dans une balise de formulaire normal (sans runat = server)? Ou bien le contrôle de statut de connexion peut-il être mis hors du formulaire? Le contenu de Header.aspx a-t-il vraiment besoin d'un formulaire?

Je voudrais bien comprendre pourquoi vous écrivez le contenu de votre page header.aspx en littéral et essayez de résoudre le problème là-bas au lieu de plonger dans le contrôle LoginStatus et de le modifier pour qu'il fasse quelque chose qui n'est pas prévu. à faire.

Une autre suggestion possible: si vous avez vraiment besoin de charger Header dans un littéral, pouvez-vous utiliser Page.LoadUserControl à la place? Cela peut résoudre automatiquement les URL pour vous? Pas sûr à 100% cependant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top