惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 司徒正美
宝玉的分享
宝玉的分享
美团技术团队
量子位
The Cloudflare Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
IT之家
IT之家
爱范儿
爱范儿
J
Java Code Geeks
博客园 - Franky
Last Week in AI
Last Week in AI
B
Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
I
InfoQ
GbyAI
GbyAI
Recent Announcements
Recent Announcements
小众软件
小众软件
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
MyScale Blog
MyScale Blog

博客园 - TerryDing

IE&FF兼容性 - event, keycode, returnvalue - TerryDing 页面生命周期(转) 在Asp.Net2.0中保存数据库链接字符串 一步一步学Linq to sql系列文章 (lovecherry) 安装 Sql Server Query Visualizer(转) - TerryDing webconfig中连接的两种写法 - TerryDing - 博客园 ToString格式大全 〔转〕 - TerryDing - 博客园 ASP.NET 2.0 页(Page)生命周期概述 [转].net 事件与生命周期 动态添加用户控件实例 - TerryDing - 博客园 2007博客园年度十佳 Top10 SqlDbType.Decimal问题 软件行业十大热点招聘职位和人才需求趋势 C# Idioms:Enum还是Enum Class(枚举类) 论“软件工程”中的分工有效吗?(转载) asp.net框架 (转) sfc/scannow是什么意思,有什么作用?(转) 如何:设置 SQL Server 的调试权限 Visual Studio Team System 2008 Team Suite (90-day Trial)(转)
ASP.NET Client-Server Interaction
TerryDing · 2006-11-30 · via 博客园 - TerryDing

ASP.NET Client-Server Interaction

"Halt App Until JavaScript Confirm Dialog Clicked". "JavaScript in code-behind problem". "How to fire ASP.NET code from JavaScript function". "Confirm delete". These are all titles of recent questions posted in various .NET forums around the web. In each case, the question poser had a fundamental misunderstanding of the client-server nature of ASP.NET.

ASP.NET is a web programming language. The web is based on the request-response model. The client makes a request, and the server generates a response. In the above examples, the coders had failed to keep this in mind, and so major confusion ensued. In a web application, code can run on the client, via JavaScript, or on the server, via C# or VB.NET code-behind. ASP.NET confuses the issue by making it appear that server code is running in response to client actions (which isn't true; server code only runs in response to a form submit). So it seems natural that, for example, a code-behind function could make an "Alert" or "Please confirm" dialog appear in the browser, wait for a response, and then continue running the server code.

This article will offer some techniques for common issues with ASP.NET client-server interaction. It would be helpful to review my other two articles, ASP.NET and HTML and ASP.NET ViewState for background on ASP.NET.

Display a "Thank You" Message

After a page is submitted and processed, you may wish to display a JavaScript message. You may want to thank the user, or simply confirm that their information was correctly posted. Or, you may have found a problem with the supplied data, and need to display a warning message. This scenario could be described as wanting a JavaScript "onload" script to run on PostBack, but not to run the first time the page loads.

For this situation, use the "RegisterStartupScript" method of the "Page" class. For this example, we'll use the same sample application as in the previous articles:

Figure 1. Visual Studio.NET

We'll add some code to the button's server-side click event.

Example 1. VS.NET "HTML" View.

private void Button1_Click(object sender, System.EventArgs e)
{
Page.RegisterStartupScript(@"startup",@"<script>alert('Thank you!');</script>");
}

The method takes two arguments, both strings. The first string is a "key". It's just a name that you can use, server-side, to refer to the script (for example, with the "IsStartupScriptRegistered" method). The second string is the script itself. Note that you must include the script tags. This is because the RegisterStartupScript method is extremely simplistic. It adds the entire contents of the second string to the end of the page's form. If you fail to provide the script tags, you'll just end up displaying text or HTML.

While it is fine to think of this as "displaying an alert when the user clicks a button", that isn't quite what is happening. For example, the button could display an alert through JavaScript, without ever making a trip back to the server.

A breakdown of what we're really doing: [1] user requests a page [2] server generates a page [3] user clicks a button [4] the page submits the form [5] the server "unwraps" the form data, HTTP Headers, and ViewState data to generate the "Button1_Click" event [6] the event handler runs, which writes a script to the page [7] the page is served back to the user [8] the script runs, displaying our "Thank you!" message. The key lesson is that we can author client-side scripts in response to events on the server.

Integrating a "Confirm" Dialog

Another common source of confusion is how best to integrate a client-side "Confirm" message with server-side form processing. Put another way, how can you make a button or link run both a client event and, conditionally, a server event?

For example, the user clicks a button to delete a record from the database. You've already written the server code and attached it to the button. Ideally, though, you want to present a dialog box asking the user if they really want to delete this record. If they answer "Yes", the browser should submit the page to the server, where the "delete" code will run. If they answer "No", then the form submission should be cancelled.

First, a short tutorial on HTML Forms and buttons. When a button is clicked, it generates a "click" event. What happens when the button is clicked depends on what is defined in the button's "onclick" handler. Consider this simple example:

Example 2. HTML button "onclick"

<input type="button" value="Click me!" onclick="alert('You clicked me.');" />

In the above example, the code to handle the click event is directly included, inline. However, it could also be contained in a JavaScript function, in which case our onclick handler would need to call the function, like so: onclick="myFunction();".

One key characteristic of HTML buttons is that the click event's function can be cancelled, if the function returns a "false" boolean.

Example 3. HTML button "onclick" with "false" boolean

<input type="button" value="Click me!" onclick="return; alert('You clicked me.');" />

Clicking this version of our button does nothing. This is because the onclick handler "returns", before any other code runs. The rest of the code is effectively "cancelled" by the return. Optionally, the "return" keyword could pass back a boolean. If the boolean is "false", the button's default action is cancelled. This doesn't make much sense in the case of regular buttons. But in our scenario, we're not dealing with a regular button. We're dealing with a submit button. Returning a "false" would cancel the form submission. Let's put the pieces together. Consider the following code:

Example 4. Cancelling a form submit

<HTML>
<head>
<script type="text/javascript">
function myFunction()
{
return false;
}
</script>
</head>
<body>
<form type="POST" action="myPage.aspx">
<input type="text" id="myTextBox" />
<input type="submit" onclick="return myFunction();">
</form>
</body>
</HTML>

Hopefully you can see that this form will never submit.

JavaScript confirm() and ASP.NET

It would be tempting then, to write a JavaScript function that displays a confirm, and if the user clicks "Yes", return "true". If they click "No", return "false". Then we'd add an "onclick" handler to our button, and we're in business. That's almost right. Remember that an ASP.NET Server Control is not HTML. It produces, or emits, HTML. If we add an "onclick" handler to an ASP Button Server Control, ASP.NET assumes we're adding a server-side event handler, not a client-side event handler.

Let's look at our sample project in Visual Studio's "HTML" view (reformatted slightly to fit this article's stylesheet). You can see that I've already added the "confirm" script. Near the bottom, you'll see our Button Server Control. If we tried to add onclick="return confirmDelete();" to the button declaration, we'd get errors when we tried to run the project. Why? Because an ASP.NET Button server control's "onclick" attribute expects you to provide a server-side function. This Button isn't an HTML submit button. It produces an HTML submit button when it runs.

Example 5. ASP.NET Webform "HTML" view

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="testsuite.WebForm1" enableViewState="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
<script type="text/javascript">
function confirmDelete()
{
var x = confirm("Are you sure you want to do this?");
if (x)
{ return true;
}
else
{ alert("Delete cancelled.");
return false;
}
}
</script>
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:TextBox id="TextBox1"
style="Z-INDEX: 101; LEFT: 96px; POSITION: absolute; TOP: 32px"
runat="server"></asp:TextBox>
<asp:Label id="Label1"
style="Z-INDEX: 102; LEFT: 40px; POSITION: absolute; TOP: 32px"
runat="server">Label</asp:Label>
<asp:Button id="Button1"
style="Z-INDEX: 103; LEFT: 192px; POSITION: absolute; TOP: 72px"
runat="server" Text="Button"></asp:Button>
</form>
</body>
</HTML>

What we have to do is add the client-side attribute to the button at run-time. We can do this by using the "Add" method of the control's "Attributes" collection.

Example 6. Adding an "onclick" in code-behind

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Text;
using System.IO;
namespace testsuite
{
/// 
/// Summary description for WebForm1.
/// 
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.TextBox TextBox1;
protected System.Web.UI.WebControls.Label Label1;
protected System.Web.UI.WebControls.Button Button1;
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
Button1.Attributes.Add("onclick","return confirmDelete();");
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// 
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// 
private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void Button1_Click(object sender, System.EventArgs e)
{
Page.RegisterStartupScript(@"startup",@"<script>alert('Record deleted.');</script>");
}
}
}