I am often asked how to intercept the postback when an <asp:Button/> is
clicked. The answer is not immediately obvious but once you know the
trick it is very straight forward.
What makes this tricky is that an <asp:Button/> renders as <input
type="submit" ... /> which means that the page will submit automatically
when the button is clicked.
This appears to not give you an opportunity to intercept the click however
the first little bit of magic you need to know is that if the button has an
"onclick" event that will fire before the page is submitted and the
second little bit of magic to know is that the boolean return value from your
"onclick" event determines if the page submission continues (return
true) or not (return false).
So, this sample code will ask you to confirm the postback and provide you and
option to cancel the submittion:
WebForm1.aspx
<%@ Page language="c#"
Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
Inherits="ButtonClick.WebForm1" %>
<!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">
</HEAD>
<body>
<form
id="Form1"
method="post"
runat="server">
<P>Click
the button to trigger the confirmButton() javascript function.</P>
<P><asp:Button
id="ButtonSubmit"
runat="server"
Text="Submit"></asp:Button></P>
<P><asp:Label
id="LabelStatus"
runat="server">Status:
</asp:Label></P>
</form>
</body>
</HTML>
WebForm1.aspx.cs
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;
namespace ButtonClick
{
public
class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button ButtonSubmit;
protected System.Web.UI.WebControls.Label LabelStatus;
private void Page_Load(object
sender, System.EventArgs e)
{
string jsConfirm = @"<script language='javascript'>
function confirmButton()
{
var agree=confirm('Are you sure you wish to continue?');
if (agree)
return true;
else
return false;
}
</script>";
Page.RegisterClientScriptBlock("confirm",jsConfirm);
ButtonSubmit.Attributes.Add("onclick","return confirmButton();");
}
#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);
}
/// <summary>
/// Required method for Designer support -
do not modify
/// the contents of this method with the
code editor.
/// </summary>
private void InitializeComponent()
{
this.ButtonSubmit.Click += new System.EventHandler(this.ButtonSubmit_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void ButtonSubmit_Click(object
sender, System.EventArgs e)
{
LabelStatus.Text = "Status: ASP Button (Server click)";
}
}
}
Easy when you know how!
A colleague of mine, Nick Francis, has just blogged about the importance of backing up your Reporting Services security key.
http://www.sentient.co.uk/blogs/nickfr/2.aspx
Without this important step you are in real trouble if someone changes the security credentials used by Report Services in your environment.
As Nick says, "Do it now!"
While browsing MSDN I just found this article which I think clearly explains the web services architecture and where each of the ws-"whatevers" fit in.
http://msdn.microsoft.com/webservices/default.aspx?pull=/library/en-us/dnwebsrv/html/introwsa.asp
Untitled Page
This blog is the first in a series where I will explorer the best way to write
a very simple piece of business logic using the current crop Microsoft
technologies starting with C# and ASP.net.
The business process I have selected is what I call "First Contact". This
is the point of initial interaction between a prospect and a business.
I will be looking at various flavours of "First Contact" in this series
starting with a simple "Contact Us" web page.
The rest of this blog demonstrates the most simples and most flawed use of
ASP.net to provide an example how badly things can go wrong!
The example consists of the following elements (source files included at the
end):
-
contactus.htm
- a web page containing the contact form to be completed.
-
addcontact.aspx - an aspx web page which handles adding the contact
details to the Contact database and notifies the customer service department
about the enquiry.
This example implements the required business logic and hence is perfectly
valid in that regard however if your business is running code like this you
should be very, very worried. The challenge is to know if you are running
good code or bad code like this.
In the next blog in this series I will highlight the issues I see with this
example and refactor it to illustrate how it can be improved.
What issues can you see in this example? Please add them to the comments
for this blog.
contactus.htm
<html>
<body>
<formmethod=getaction="addcontact.aspx">
<imgsrc="generiCoLogo.gif">
<br>
<table>
<tr>
<td>
Name
</td>
<td>
<inputname="name"type="text">
</td>
</tr>
<tr>
<td>
Email
</td>
<td>
<inputname="email"type="text">
</td>
</tr>
<tr>
<td>
Phone
</td>
<td>
<inputname="phone"type="text">
</td>
</tr>
<tr>
<td>
Message
</td>
<td>
<textareaname="message"></textarea>
</td>
</tr>
</table>
<inputid="Send"type="submit"value="Send">
</form>
</body>
</html>
addcontact.aspx
<%@ Page Language="C#" %>
<html>
<body>
<%
if (Request["name"] == "" ||
Request["email"] == "" ||
Request["phone"] == "" ||
Request["message"] == "")
{
Response.Write("<h1>Oops!</h1>Please enter name, email, phone and message.<br><br>Click <a href=\"contactus.htm\">here</a> to go back.");
}
else
{
string message = string.Format("Name: {0}\nEmail: {1}\nPhone: {2}\nMessage: {3}",
Request["name"], Request["email"], Request["phone"], Request["message"]);
System.Web.Mail.SmtpMail.Send("nobody@sentient.co.uk","customerservice@sentient.co.uk","FirstContact", message);
string sql = string.Format("INSERT INTO Contacts(name, email, phone, message) VALUES ('{0}','{1}','{2}','{3}')",
Request["name"], Request["email"], Request["phone"], Request["message"]);
System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection("Server=localhost;Database=FirstContact;User ID=sa;Password=");
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(sql, connection);
command.Connection.Open();
if (command.ExecuteNonQuery() > 0)
{
Response.Write("<h1>Thank-you</h1>One of our customer service representatives will be in touch with you shortly.");
}
else
{
Response.Write("<h1>Sorry!</h1>There was a problem please <a href=\"contactus.htm\">try again</a>.");
}
connection.Close();
}
%>
</body>
</html>
A colleague of mine, Nick Francis, recommended a handy utility to simplify the process of taking source code from Visual Studio and including it in a blog.
For those of you who haven’t tried to do this you’ll be surprised to find that Visual Studio doesn’t provide HTML on the clipboard but instead gives you either RTF or plain text meaning that Visual Studio’s colour highlighting is lost in translation.
CopySourceAsHTML is a Visual Studio add-in which provides a Copy as HTML command which can be assigned to a toolbar or menu item and enables you to paste beautifully formatted HTML source code directly into you favourite HTML editor.
CopySourceAsHTML can be downloaded from Colin Collers blog at the following location:
http://www.jtleigh.com/people/colin/blog/archives/2004/11/copysourceashtm_2.html
Thanks also go to Colin for include an extra feature at my request to remove the indentation before the source you are copying resulting in it being flush against the left border. You are a "top chap".
I came across a new term yesterday "idempotent".
An operation is idempotent if it produces the same result if performed one or more times.
W3 define idempotent as "Property of an interaction whose results and side-effects are the same whether it is done one or multiple times."
So an operation to get a product list would be considered idempotent but an operation to place (post) an order would not be.
What I didnt realise was that HTTP defines GET to be idempotent and POST to not be. This means that if you use a GET to perform a non-idempotent operation such as place an order you could potentially find some bit of middleware legitimately replaying that GET multiple times assuming it is fine because GET is non-idempotent.
So just because you can write "placeorder.aspx?itemId=38" doesnt mean you should!