1

atlas客户端页面周期事件及实践:自定义错误

by 刘武 25. 七月 2009 11:11

在系统中异常总是难以避免的,通常我们应该尽量避免将异常信息直接呈现给用户,因为很多情况下这些信息用户是无法理解的。看下面的例子:


<asp:UpdatePanel ID="up" runat="server" UpdateMode="conditional">
    <ContentTemplate>
        <asp:Button ID="btnTest" runat="server" Text="Test"
        OnClick="btnTest_Click" />
    </ContentTemplate>
</asp:UpdatePanel>
protected void btnTest_Click(object sender, EventArgs e)
{
    throw new System.NullReferenceException();      
}
该例中直接抛出了一个找不到引用的异常,atlas默认的处理方式是在客户端弹出该异常信息的对话框:

这显然不是我们想要的,

一种处理方式就是修改该提示信息的内容

可以在ScriptManager控件的AsyncPostBackError事件中捕获异常并修改错误的提示信息:


<asp:ScriptManager ID="sm" runat="server"
    OnAsyncPostBackError="sm_AsyncPostBackError">
</asp:ScriptManager>
protected void sm_AsyncPostBackError(object sender,
    AsyncPostBackErrorEventArgs e)
{
    sm.AsyncPostBackErrorMessage = "发生了未知错误,请联系管理员";
}

 

 也许你不想采用弹出框的形式

那么就可以在页面周期中自定义错误处理:添加以下javascript脚本:


<script type="text/javascript" language="javascript">          
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
function EndRequestHandler(sender, args)
{
    var error = args.get_error();
   if (error != undefined)
   {
       $get('err').innerHTML =error.message;           
   }
   args.set_errorHandled(true);
}
</script>
<div id="err"></div>
注意一定要加上args.set_errorHandled(true)表示该错误已经处理,不需要默认的处理方式了。

 

很多情况下这样还不够,在一些表单型的页面往往需要根据错误来设置输入框的焦点,以改善用户体验。

atlas可以在服务端用ScriptManager.GetCurrent(Page).SetFocus()方法设置焦点,但在异常发生时就不会执行了,因此我们需要自己实现该功能。这时js里的eval函数帮了我们大忙,因为他可以把字符串当作代码来执行,所以我们可以在代码放在异常信息里:


<script type="text/javascript" language="javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
function EndRequestHandler(sender, args)
{
    var error = args.get_error();
   if (error != undefined)
   {           
       eval(error.message);       
   }
   args.set_errorHandled(true);
}
</script>
<asp:UpdatePanel ID="up" runat="server" UpdateMode="conditional">
    <ContentTemplate>
        <asp:Button ID="btnTest" runat="server" Text="Test"
        OnClick="btnTest_Click" />
        <asp:TextBox ID="txt1" runat="server"></asp:TextBox>
    </ContentTemplate>
</asp:UpdatePanel>
protected void btnTest_Click(object sender, EventArgs e)
{
    string s = "alert('发生了未知错误,请联系管理员');"+
        "$get('"+txt1.ClientID+"').focus()";
    throw new ApplicationException(s);
}

相关阅读:

  1. atlas客户端页面周期事件及实践:防止重复提交
  2. atlas客户端页面周期事件及实践:客户端验证

Tags: ,

技术生涯

0

atlas客户端页面周期事件及实践:防止重复提交

by 刘武 19. 七月 2009 16:51

关于防止页面重复提交的方法,前面的文章都有提到,可以参考:

  1. 利用模态DIV结合UpdateProgress防止页面重复提交
  2. ASP.NET中在点击按钮后将该按钮设为不可用的若干情况
  3. atlas客户端页面周期事件及实践:客户端验证

本文介绍利用atlas页面周期事件来实现该功能的方法,其实原理很简单,就是在提交之前在beginRequest事件中将按钮设为不可用,然后在endRequest事件中将按钮状态恢复。请看下面的例子


<form id="form1" runat="server">
    <asp:ScriptManager ID="sm1" runat="server">
    </asp:ScriptManager>
    <script type="text/javascript">
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(SetButtonStatus);
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(SetButtonStatusEnd);
    var postButton ;      
    function SetButtonStatus(sender,args)
    {
        postButton =args.get_postBackElement();           
        if (postButton.id=='btnPostBack')
        {
            postButton.disabled='disabled';
        }
    }
    function SetButtonStatusEnd(sender,args)
    {
        if (postButton.id=='btnPostBack')
        {
            postButton.disabled='';
        }
    }
    </script>
    <asp:UpdatePanel ID="up1" runat="server" UpdateMode="conditional">
        <ContentTemplate>
            <%=DateTime.Now.ToString() %>
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="btnPostBack" EventName="Click" />
        </Triggers>
    </asp:UpdatePanel>
    <asp:Button ID="btnPostBack" runat="server" Text="LogIn" OnClick="btnPostBack_Click" />
</form>
[code=c#]protected void btnPostBack_Click(object sender, EventArgs e)
{
    System.Threading.Thread.Sleep(2000);
}[/code]

注意,该按钮必须提交了一个异步回发请求该方法才会有效。

参考:

  1. beginRequest 
  2. BeginRequestEventArgs 
  3. endRequest 
  4. EndRequestEventArgs

Tags: , ,

技术生涯

0

atlas客户端页面周期事件及实践:客户端验证

by 刘武 15. 七月 2009 21:06

大家都知道asp.net页面有很多服务端的周期事件,随着atlas的推出,微软又进一步引入了客户端的周期事件。主要包含以下几个

  1. initializeRequest  发生在页面初始化之前
  2. beginRequest 发生在提交数据之前
  3. pageLoading  发生在提交进行时
  4. pageLoaded 发生在提交完成,页面刷新之后
  5. endRequest 发生在整个操作完成之后

本篇根据笔者的项目经验,总结了这些事件主要用途:

一 客户端验证

客户端验证是BS系统中必不可少的操作,他发生在向服务器提交数据之前。因此我们可以在initializeRequest事件中来完成该操作。下面的例子模拟了一个登录的过程,在点击登录按钮的时候先检查是否有其他操作正在进行,然后再检查用户名和密码是否为空,检查通过后再提交服务端,否则就取消请求。


<form id="form1" runat="server">
    <asp:ScriptManager ID="sm1" runat="server">
    </asp:ScriptManager>
    <script type="text/javascript">
    Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(CheckInput);
    function CheckInput(sender,args)
    {
        var pass=true;
        var prm = Sys.WebForms.PageRequestManager.getInstance();
       
        if(prm.get_isInAsyncPostBack())
        {
            alert("请勿重复登陆");
            pass=false;
        }
        else
        {
            var no = $get('txtAccount');
            var pwd = $get('txtPwd');
            if(no.value=='')
            {
                alert('用户名不能为空');
                no.focus();
                pass=false;
            }
            else if(pwd.value=='')
            {
                alert('密码不能为空');
                pwd.focus();
                pass=false;
            }
        }
        if(!pass)
        {
            args.set_cancel(true);
        }
    }
    </script>
    <asp:UpdatePanel ID="up1" runat="server" UpdateMode="conditional">
        <ContentTemplate>
            <asp:TextBox ID="txtAccount" runat="server"></asp:TextBox>
            <asp:TextBox ID="txtPwd" runat="server" TextMode="password"></asp:TextBox>
            <asp:Button ID="btnLog" runat="server" Text="LogIn" OnClick="btnLog_Click" />
        </ContentTemplate>
    </asp:UpdatePanel>
</form>
protected void btnLog_Click(object sender, EventArgs e)
{
    System.Threading.Thread.Sleep(2000);
    if (!(txtAccount.Text == "liuwu" &&
        txtPwd.Text == "liuwu.net"))
    {
        throw new ApplicationException("用户名或密码错误");
    }
}
例子中使用 Sys.WebForms.PageRequestManager.getInstance()来获取当前页面的PageRequestManager实例,并使用该实例的add_initializeRequest方法来添加initializeRequest事件,最后使用InitializeRequestEventArgs.set_cancel(true)方法来取消当前的请求。注意如果用户名或密码不正确的话,服务端会抛出异常,默认情况下,atlas会在客户端弹出对话框来显示异常信息,后面的文章会介绍如何自定义错误提示。

参考:

  1. initializeRequest
  2. InitializeRequestEventArgs
  3. atlas客户端页面周期事件及实践:防止重复提交

Tags: , , ,

技术生涯

9

ASP.NET中在点击按钮后将该按钮设为不可用的若干情况

by 刘武 7. 七月 2009 21:33

项目中经常出现用户重复提交的情况,为了防止这种情况,最常用的方法就是在用户点击按钮后将该按钮设为不可用,笔者在实际开发当中遇到了多种不同的情况,在此做个小结,以供参考。

第一种情况是非submit类型的按钮

这种情况比较简单,只要在客户端添加事件,将按钮设为不可用就可以了。看下面的代码:


<form id="form1" runat="server">
        <asp:Label ID="lbl" runat="server"></asp:Label>
        <asp:Button ID="btn" runat="server" Text="Test"
            OnClick="btn_Click" OnClientClick="this.disabled=true"
            UseSubmitBehavior="false" />
</form>
protected void btn_Click(object sender, EventArgs e)
{
    System.Threading.Thread.Sleep(1000);
    lbl.Text = DateTime.Now.ToString();
}

第二种情况是submit类型的按钮

此时第一种方法就不行了,按钮被设为DISABLED之后就无法完成提交,我们可以适当修改代码:


<form id="form1" runat="server">
    <asp:Label ID="lbl" runat="server"></asp:Label>
    <asp:Button ID="btn" runat="server" Text="Test"
        OnClick="btn_Click"/>
</form>
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        btn.OnClientClick = "this.disabled=true;" +
            GetPostBackEventReference(btn);
    }
}
与第一种方法不同的是我们在Page_Load中给按钮添加客户端事件,并附加了GetPostBackEventReference。但这样做还有个缺陷,在第一提交回发完成以后,再点击按钮就会失败,因此我们需要去掉if (!Page.IsPostBack)这句,也就是每次回发都要重复绑定客户端事件。

第三种情况跟第一种类似,只是多了个UpdatePanel


<asp:UpdatePanel ID="up1" runat="server" >
    <ContentTemplate>
        <asp:Label ID="lbl" runat="server"></asp:Label>
        <asp:Button ID="btn" runat="server" Text="Test"
            OnClick="btn_Click"
            OnClientClick="this.disabled=true;"
            UseSubmitBehavior="false" />
    </ContentTemplate>
</asp:UpdatePanel>

第四种情况也是在UpdatePanel里面,不过和第二种情况一样,也是Submit类型的按钮

和第二种情况不同的是,我们只需要在第一次加载的时候绑定客户端事件就可以了,即在 if (!Page.IsPostBack){}中绑定事件。

第五种和第四种不同的是,按钮在UpdatePanel外面,通过触发器来刷新指定的UpdatePanel

如果按第四种的方法,可以在点击按钮后设为不可用,但回发完成以后该按钮不会恢复可用状态:


<asp:UpdatePanel ID="up1" runat="server">
    <ContentTemplate>
        <asp:Label ID="lbl" runat="server"></asp:Label>
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="btn"
            EventName="Click" />
    </Triggers>
</asp:UpdatePanel>
<asp:Button ID="btn" runat="server" Text="Test"
    OnClick="btn_Click" />

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        btn.OnClientClick = "this.disabled=true;" +
            GetPostBackEventReference(btn);
    }
}

protected void btn_Click(object sender, EventArgs e)
{
    System.Threading.Thread.Sleep(1000);
    lbl.Text = DateTime.Now.ToString();
}

为了解决这个问题,最简单的方法就是将该按钮放在另一个UpdatePanel里面,这样每次都可以恢复原状态了。另外还可以根据Atlas的页面周期,在提交完成以后显式将该按钮设为可用。

Tags: , ,

技术生涯

0

利用模态DIV结合UpdateProgress防止页面重复提交

by 刘武 9. 三月 2009 22:27

页面在提交的时候可能因为服务器处理慢而导致用户多次重复的点击某个按钮,因此我们需要防止用户这么做,常见的方法是在客户端把该按钮disable掉,但页面处理完或出现错误的时候又需要恢复按钮的状态,这样操作起来往往比较复杂,在atlas页面中,我们可以利用模态DIV和UpdateProgress来实现同样的效果,实现起来也比较简单 。看下面的页面


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>无标题页</title>
    <style type="text/css">
    #modalDiv
    {
        position: absolute;
        top: 0%;
        left: 0%;
        width: 100%;
        height: 100%;
        z-index:1001;
        background-color: black;
        opacity:.60;
        filter: alpha(opacity=10);
    }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="0">
            <ProgressTemplate>
                <div id="modalDiv">
                </div>
            </ProgressTemplate>
        </asp:UpdateProgress>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Button ID="Submit" runat="server"
                    OnClick="Submit_Click" Text="Submit" />
            </ContentTemplate>
        </asp:UpdatePanel>
    </form>
</body>
</html>

Tags: , , , ,

技术生涯

Powered by BlogEngine.NET 1.6.1.9  登录
Original Design by Laptop Geek, Adapted by onesoft