Search code examples
vb.netwebformsasp.net-membership.net-4.8

a page can have only one server-side form tag - allow unauthenticated access in aspnet membership provider


I have been given an "old-school" application that uses asp.net membership provider for logins. My aim is to redirect users to "ChangePassword.aspx" page when they try to login - if they have a dirty flag set in the db.

    Dim hash As SecurePassword = New SecurePassword()
    If Not hash.IsAccountSecurelyUpgraded(myLogin.UserName) Then
        Response.Redirect("/aspnet_membership/ChangePassword.aspx") 
    End If

    If Membership.ValidateUser(myLogin.UserName, myLogin.Password) Then
            ...some code...
      End If

I get error

A page can have only one server-side form tag

ChangePassword.aspx

 <%@ Page Language="VB" AutoEventWireup="false" Inherits="VL.ChangePassword" Codebehind="ChangePassword.aspx.vb" %>
<%@ Register TagPrefix="uc1" TagName="Header" Src="../UI/Template/Header.ascx" %>
<%@ Register TagPrefix="uc1" TagName="Footer" Src="../UI/Template/Footer.ascx" %>

<uc1:header id="Header1" runat="server"></uc1:header>
<form id="ChangePassword" runat="server">
<h2>Change Your Password</h2>

...
</form>     
<uc1:footer id="Footer1" runat="server"></uc1:footer>

Other Urls in the site don't give this error. (they give unauthenticated error)

Site.master

<body>
<div id="wrapper">

    <form id="form1" runat="server">
    
        <div id="header">
            <span class="title">User Account </span><br />
            
            <span class="breadcrumb">
                <asp:SiteMapPath ID="SiteMapPath1" runat="server">
                </asp:SiteMapPath>
            </span>
        </div>
    
        <div id="content">
            <asp:contentplaceholder id="MainContent" runat="server">
              <!-- Page-specific content will go here... -->
            </asp:contentplaceholder>
        </div>
        
        <div id="navigation">
            <asp:ContentPlaceHolder ID="LoginContent" runat="server">
                <asp:LoginView ID="LoginView1" runat="server">
                    <LoggedInTemplate>
                        Welcome back,
                        <asp:LoginName ID="LoginName1" runat="server" />.
                        <br />
                        <asp:HyperLink ID="lnkUpdateSettings" runat="server" NavigateUrl="~/aspnet_membership/AdditionalUserInfo.aspx">Update Your Settings</asp:HyperLink>
                    </LoggedInTemplate>
                    <AnonymousTemplate>
                        Hello, stranger.
                    </AnonymousTemplate>
                </asp:LoginView>
                <br />
                <asp:LoginStatus ID="LoginStatus1" runat="server" LogoutAction="Redirect" LogoutPageUrl="~/Logout.aspx" />
                
                <br /><br />
            </asp:ContentPlaceHolder>
             <ul>...</ul>

<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" />
        </div>
    </form>
</div>
</body>

Solution

  • It turned out the header UserControl had scripts added in codebehind.

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        
        LoginPanel.Visible = Not UserManager.IsLoggedIn()
        If System.IO.Path.GetFileName(Request.ServerVariables("SCRIPT_NAME")) = "ChangePassword.aspx" Or
            System.IO.Path.GetFileName(Request.ServerVariables("SCRIPT_NAME")) = "RecoverPassword.aspx" 
            (System.IO.Path.GetFileName(Request.ServerVariables("SCRIPT_NAME")) = "contact.aspx" And Not UserManager.IsLoggedIn()) Then
            LoginPanel.Visible = False
        End If
        If Not Page.IsPostBack Then
            Login_Check()
        End If
    End Sub 
    

    After adding, ChangePassword.aspx to the list, it started working