2

我对默认 ASP.NET身份验证控件的行为感到有些困惑,确切地说是其生命周期。

在我的MasterPage中,我添加了一个LoginView控件,它显示了漂亮的 [Login] 或 [Logout] 链接。当我登录并单击 [注销] 时,我将控件设置为执行重定向到应用程序的主页。

在内部,当点击“注销”时,会触发回发。发生以下步骤(当然还有其他步骤):

  1. 触发回发的页面被重新初始化
  2. 触发回发的页面被重新加载
  3. LoggingOut 事件被触发
  4. LoggedOut 事件被触发
  5. 触发回发的页面是 PreRendered
  6. 重定向发生
  7. 目标页面已加载(在我的情况下为 LoggedOut.aspx)

在大多数页面上,这都很好。但是有些页面期望一些数据被初始化以使其渲染正确发生。发生此注销回发时,数据未正确初始化,但页面仍处于 PreRendered 状态,这会导致一些...“意外行为”>_<

因此,我的问题是双重的:

  • 由于页面根本不会显示,为什么会发生此渲染步骤?
  • 有没有办法防止渲染发生?

非常感谢。蒂姆

PS:如果您想自己尝试一下,这里有一个小的 VS2010 示例项目,向您展示调用顺序和页面生命周期http://dl.dropbox.com/u/11764136/LoginTest.7z

4

6 回答 6

0

有一种方法可以防止页面的实际呈现。

重定向页面时停止处理当前请求。这可以通过为 Response.Redirect 方法提供一个 true 参数来完成:

Response.Redirect("http://somewhere", true);

您也可以通过调用 Response.Close(); 手动执行此操作;

于 2012-04-15T11:10:23.697 回答
0

您是否使用 if(!isPostBack) 测试来控制应该渲染/重新初始化什么以及不应该渲染什么?

于 2012-04-15T11:33:20.087 回答
0

Venemo 的回答给了我一个似乎可行的想法。

我没有依赖LoginStatus组件来执行重定向,而是将托管LoginStatus组件的 MasterPage 注册到LoginStatus.LoggedOut事件并在调用 PreRender 步骤之前“手动”触发重定向。

protected void Page_Load(object sender, EventArgs e)
{
   MasterLoginStatus.LoggedOut += new EventHandler(OnUserLoggedOut);
}

private void OnUserLoggedOut(object sender, EventArgs e)
{
   Response.Redirect("~/LoggedOut.aspx", true);
}

我担心这样做LoginStatus可能会使组件保持肮脏,但到目前为止我还没有发现任何问题,例如“在证明其他情况之前有效”。

仍然是“为什么组件的行为如此”的问题,但我想这是一个尚未得到解答的设计决策。

编辑:这工作正常,直到您遇到“登录”操作的相同问题。还没有找到解决这个问题的方法。

于 2012-04-17T12:24:54.013 回答
0

我有一个 DevExpress 控件(报告 DocumentMap)的严重问题,当最终用户单击 LoginStatus 控件上的注销链接时,它有时会绕过缓存机制请求整个报告。我已经尝试了很多方法来阻止“注销”回发,这样就不会生成报告(有些报告需要 5 分钟才能呈现,所以注销操作有时需要那么长时间)。我认为这与您的问题相似:如果用户正在注销,您不想进行任何繁重的处理。所以我尝试了一种不同的方法:为什么我没有认识到回发确实是注销回发?我的所有页面都继承自基本页面,因此我在基本页面中设置了以下代码:

public bool IsLoggingOut { get; private set; }

protected override void OnPreInit(EventArgs e)
{
    base.OnPreInit(e);
    var eventTarget = Request.Params.Get("__EVENTTARGET");
    IsLoggingOut = eventTarget != null && eventTarget.Contains("HeadLoginView$HeadLoginStatus");
}

现在我需要在我的页面中做的就是用 !IsLoggingOut... 的测试来包围任何繁重的处理,您甚至可以重定向到 LoggedOut 页面而无需处理任何事件,就像这样:

protected override void OnLoad(EventArgs e)
{ 
    if (IsLoggingOut)
        Response.Redirect("~/LoggedOut.aspx", true);
}

即使您更喜欢使用事件处理程序来执行重定向,能够知道回发确实是由于注销点击是一件好事!

于 2012-07-23T01:00:46.810 回答
0

就我而言,我遇到了LoginStatus控件的问题。Render我不明白为什么当用户单击“注销”时回发和页面是一个有用的设计。通过一些测试,我发现我必须让页面经历它的整个生命周期,所以Reponse.End()Response.Transfer()没有工作。

我的解决方案是为 LoginStatusLoggedOut事件添加事件处理程序,然后在用户注销时覆盖Render()母版页中的方法以不执行任何操作。实际上,我将 LoginStatus 嵌套在母版页中的用户控件中,因此我不得不冒泡该事件。

在包含该控件的用户控件中LoginStatus,我为该事件添加了一个事件处理程序LoggedOut。在 UserStatus.aspx 文件中:

<asp:LoginStatus runat="server" ID="loginStatusDefault" OnLoggedOut="loginStatusDefault_LoggedOut" ... />

然后在代码隐藏中:

public event EventHandler LoggedOut;
protected void loginStatusDefault_LoggedOut(object sender, EventArgs e)
{
    if (this.LoggedOut != null)
     this.LoggedOut(sender, e);
}

现在在母版页 default.master 中,我已经包含了 UserStatus 控件:

<c:userstatus ID="ctlUserStatus" runat="server" />

在代码隐藏中:

protected void Page_Init(object sender, EventArgs e)
{
    ctlUserStatus.LoggedOut += ctlUserStatus_LoggedOut;

    ...
}

bool IsLoggedOut { get; set; }

void ctlUserStatus_LoggedOut(object sender, EventArgs e)
{
    IsLoggedOut = true;
}

protected override void Render(HtmlTextWriter writer)
{
    if (!IsLoggedOut)
        base.Render(writer);
}

对我来说,页面渲染是用户单击“注销”时爆炸的原因,因此这解决了所有页面的问题。

于 2014-10-21T19:07:32.430 回答
0

我所做的是让注销链接或注销控件重定向到另一个页面“Logout.aspx”,然后处理注销代码。实际上效果很好。

protected void LoginStatus1_LoggingOut(object sender, EventArgs e) 
        {

            Response.Redirect("~/Logout.aspx");
        }
于 2014-10-28T20:10:08.420 回答