第一,切不能在里面加Login控件来妄想无刷新回调,我看了Login控件的源代码,它的SignOn处理中调用了Redirect方法,重定向浏览器你还能无刷么?所以,嘿嘿!!!要无刷,还得自给自足,自行写Login UI和登录代码。同样,想无刷注销也别用LoginStatus,它的处理也调用了Redirect.
前天做了个用Atlas的UpdatePanel包装LoginView的登录例子,代码骨架如下:
<asp:Panel runat="server" CssClass="modalPopup" style="display:none">
<atlas:UpdatePanel runat="server">
<asp:LoginView runat="server">
<AnonymousTemplate>
//自己的登录UI和Login按钮处理
</AnonymousTemplate>
<LoggedInTemplate>
您好!<asp:LoginName runat="server" />
</LoggedInTemplate>
</ContentTemplate>
</atlas:UpdatePanel>

登录处理代码:
protected void LoginButton_Click(object sender, EventArgs e)

{

if(Page.IsValid)
{
TextBox userName = this.LoginView1.FindControl("UserName") as TextBox;
TextBox password = this.LoginView1.FindControl("Password") as TextBox;
bool isAuthenticated = LoginUtil.GetProvider("SQLMembershipProvider").ValidateUser(userName.Text, password.Text);
if (isAuthenticated)

{
CheckBox remMe = this.LoginView1.FindControl("RememberMe") as CheckBox;
FormsAuthentication.SetAuthCookie(userName.Text, remMe.Checked);
}
else

{
//FormsAuthentication.RedirectToLoginPage("loginfailure=1");
Literal failure = this.LoginView1.FindControl("FailureText") as Literal;
failure.Text = "登录错误!";
}
}
}
首先,我要说几点:
第一,切不能在<AnonymouseTemplate>里面加Login控件来妄想无刷新回调,我看了Login控件的源代码,它的SignOn处理中调用了Redirect方法,重定向浏览器你还能无刷么?所以,嘿嘿!!!要无刷,还得自给自足,自行写Login UI和登录代码。同样,想无刷注销也别用LoginStatus,它的处理也调用了Redirect.
但是尽管这样,我写的代码运行后,却出现了一个很奇怪的现象,在我输入正确信息后第一次点登录时,数据被提交,输入框数据也被清空了,Anonymous却没有转到LoggedIn。胡乱再输入一堆错误的用户名和密码后再点击一次登录,LoginView的模板从
Anonymous转到LoggedIn.
这是怎么回事呢?为什么第一次异步提交后模板没有被切换?为什么第二次提交错误的信息后,模板居然改变成LoggedIn了?
嘿嘿,如果你不去看微软自家的实现,你可能一辈子都不知道为什么。于是,隔日我又反编译之,获取LoginView源码,来解读一番,顿知晓其究竟。
首先,请你看看模版是根据什么切换的,
大家内行都知道,ASP.NET控件生成HTML有2步:
OnPreRender -> Render
那么,请各位来看看LoginView中的这两个方法:

protected internal override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
//预render时调用GetTemplateIndex()来获取相应模板
this.TemplateIndex = this.GetTemplateIndex();
this.EnsureChildControls();
}

protected internal override void Render(HtmlTextWriter writer)
{
this.EnsureChildControls();
base.Render(writer);
}

OnPreRender中调用了GetTemplateIndex()来获取模板索引, 不用我说,呆会真正Render的时候,肯定是根据TemplateIndex来选择是用Anonymous还是LoggedIn还是RoleGroup模板了。所以关键就是看GetTemplate是根据什么条件来选择模板的。(Render就不用看了,只是调用了一个EnsureChildControls和几基类的Render, 显然没有什么名堂).
接下来,请大家来看看我们的GetTemplateIndex方法了,如下:
//获得模板索引

private int GetTemplateIndex()
{
//根据请求是否被认证来返回相应的模板
if ((base.DesignMode || (this.Page == null)) || !this.Page.Request.IsAuthenticated)

{
return 0;
}
IPrincipal principal1 = LoginUtil.GetUser(this);
int num1 = -1;
if (principal1 != null)

{
num1 = this.RoleGroups.GetMatchingRoleGroupInternal(principal1);
}
if (num1 >= 0)

{
return num1 + 2;
}
return 1;
}

值得注意的是,第三行中的!this.Page.Request.IsAuthenticated, 它是根据Request对象IsAuthenticated的值来判断该返回相应模板的索引。
显然,我之前的代码,在第一次登录时,发送过去的Request对象的IsAuthenticated属性的值显然为false( Request.IsAuthenticated返回的是HttpContext.Current.IsAuthenticated),因为还没有登录成功被认证,并且,我做过测试,在FormsAuthentication.SetAuthCookie(userName.Text, remMe.Checked);之后, Trace Request.IsAuthenticated的值,仍为false. 所以这就导致第一次提交登录后并没有切换模板到LoggedIn, 那为什么第二次胡乱输入切又会改变呢?这很简单,当我们第二次提交登录时,尽管用户名和密码可能都是错误的,但是,这时的Request的IsAuthenticated属性已经是true了,所以第二次的提交当然会改成LoggedIn了。
如果你细心,你可能会问,既然第一次Request.IsAuthenticated为false, 并且GetTemplateIndex()是通过Request.IsAuthenticated来选择模板,那岂非传统的Login亦如此,需两次登录Click方可。这里,你先清楚一点,不管是atlas封装的无刷新调用也好,还是传统的Login控件,他们在登录处理时都调用了LoginView的Render,这显然了,否则在altas下n次也转换不了模板。 那么既然都是调用了,为何结果不同呢?呵呵,这就得看HttpContext.Current.IsAuthenticated何时变为true,此番待下回分解。