KeyLimeTie Blog

SQL Server 2005 Script to Generate INSERT statements

By Brian Pautsch – 3/24/2009. Posted to Code Snippets.

When it comes time to migrate code and database changes for a project, you often need to create new rows in the various environments (i.e. QA, Staging, Production). Some migrations involve creating rows for list tables, including states, countries, status codes, etc. One option is to write the INSERT statements one at a time, but that is too time consuming and is prone to errors. Instead, you can use the SQL script listed below.

When you run the script against a table, you'll notice 2 things:
1. All data values are converted to HEX so you don't need to worry about escaping quotes.
2. If the table has an identity column, the script will generate the IDENTITY_INSERT commands as well.

Download SQL script

/* EXAMPLES
--Entire table
CreateInserts 'Webpages'
--Entries WHERE WebpageID > 100
CreateInserts 'Webpages', 'WebpageID > 100'
--Entries WHERE WebpageID > 100 ORDER BY Title
CreateInserts 'Webpages', 'WebpageID > 100', 'Title'
*/
--If stored procedure already exists, drop it IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[CreateInserts]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[CreateInserts] GO --Create the stored procedure CREATE PROC CreateInserts @tableName nvarchar(100), @whereClause nvarchar(MAX) = '', @orderByClause nvarchar(MAX) = '' AS --Declare variables DECLARE @tableHasIdentity bit DECLARE @sql nvarchar(MAX) DECLARE @cols nvarchar(MAX) DECLARE @vals nvarchar(MAX) SET @cols = '' SET @vals = '' --Determine if table has an identity column SELECT @tableHasIdentity = OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @tableName --Do we need 'SET IDENTITY_INSERT tableName ON' statement? IF @tableHasIdentity = 1 BEGIN SET @sql = 'SELECT TOP 1 ''SET IDENTITY_INSERT ' + @tableName + ' ON '' FROM ' + @tableName EXEC sp_executesql @sql END --Build list of columns and values SELECT @cols = @cols + ',' + '[' + column_name + ']', @vals = @vals + '+'',''+ISNULL(master.dbo.fn_varbintohexstr(cast([' + column_name + '] as varbinary(max))),''NULL'')' FROM INFORMATION_SCHEMA.columns WHERE TABLE_NAME = @tableName and DATA_TYPE != 'timestamp' --Build SQL string SET @sql = 'SELECT ''INSERT INTO [' + @tableName + '] (' + SUBSTRING(@cols,2,LEN(@cols)) + ') ' + 'VALUES (''+' + SUBSTRING(@vals, 6, LEN(@vals)) + '+'')'' FROM ' + @tableName --Adjust @whereClause and @orderByClause IF LEN(@whereClause) > 0 SET @sql = @sql + ' WHERE ' + @whereClause IF LEN(@orderByClause) > 0 SET @sql= @sql + ' ORDER BY ' + @orderByClause --Execute SQL string exec sp_executesql @sql --Do we need 'SET IDENTITY_INSERT tableName OFF' statement? IF @tableHasIdentity = 1 BEGIN SET @sql = 'SELECT TOP 1 ''SET IDENTITY_INSERT ' + @tableName + ' OFF '' FROM ' + @tableName EXEC sp_executesql @sql END GO

Migrating ASP.NET Applications to IIS 7.0 Integrated Mode

By Brian Pautsch – 11/14/2008. Posted to Code Snippets.

Upgrading an ASP.NET application from IIS 6.0 and lower (Classic ASP.NET Integration Mode) to IIS 7.0 (Integrated Mode) can be a lot of work. To help, Microsoft provides an application that does the work for you.

IIS 7.0 takes care of migrating the application by using the APPCMD.EXE command line tool to perform the migration. The migration error message contains the command that is executed in command line window (which you must run--right click the Programs\Accessories\Command Prompt icon, and choose "Run as administrator") in order to instantly migrate your application to Integrated mode.

The basic format of the migration command is the following:

%windir%\system32\inetsrv\APPCMD.EXE migrate config <Application Path>

where is the virtual path of the application containing the site name, such as "Default Web Site/app1".

When migration is complete, your application runs in both Integrated and Classic modes without a problem.

Note: If you change the configuration after migration, the server will not prompt you to migrate again. After initial migration, you must make sure that your configuration remains in sync between the two modes – manually migrate the application again using the APPCMD.EXE command line tool.

Source: http://learn.iis.net/page.aspx/243/aspnet-integration-with-iis7/

Prevent ASP.NET Pages From Caching

By Brian Pautsch – 10/17/2008. Posted to Code Snippets.

We recently came across a scenario where an ASP.NET page was caching on the user's browser and causing issues. ASP.NET pages are dynamic and their content should never cache. To force the browser to not cache the page, add the following code:

Code-behind
1Response.AppendHeader("Cache-Control", "no-cache; private; no-store; 
must-revalidate; max-stale=0; post-check=0; pre-check=0; max-age=0"
); 2Response.AppendHeader("Pragma", "no-cache"); 3Response.AppendHeader("Keep-Alive", "timeout=3, max=993"); 4Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); //Some random old date


HTML META tags
1<meta http-equiv=expires content=-1>
2<meta http-equiv=Cache-Control CONTENT=no-cache>
3<meta http-equiv=Pragma CONTENT=no-cache>

How to safely escape invalid XML characters

By Brian Pautsch – 9/25/2008. Posted to Code Snippets.

When saving strings to XML, it important to escape invalid characters. The following table shows the invalid XML characters and their escaped equivalents.

Invalid XML Character Replaced With
< &lt;
> &gt;
" &quot;
' &apos;
& &amp;

Rather than write code to do a bunch of replaces, use this one line of code:

1string escapedText = System.Security.SecurityElement.Escape(input);

By using this built-in .NET method, you ensure your strings are properly escaped.

To learn more about this method and see developer's feedback (some people have concerns), go to
http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape(VS.80).aspx

How to validate strings for XML

By Brian Pautsch – 9/2/2008. Posted to Code Snippets.

Back on 3/28/2008, we published a blog titled How to check for hexidecimal characters. I used this code as a basis to write a method to ensure only valid UTF-8 characters are in a string. If invalid characters are in an XML document, the document cannot be consumed by an application and can cause a complete website outage (depending on how it's used). The following method looks for invalid XML characters.

1private static bool IsValidString(string input)
2{
3    try
4    {
5        //Trim input string
6        input = input.Trim();
7
8        //If blank, no need to validate
9        if (input.Length == 0)
10            return true;
11
12        //Loop through characters
13        foreach (char currentChar in input)
14        {
15            if (currentChar == 0x9 || // \t = 9
16                currentChar == 0xA || // \n = 10
17                currentChar == 0xD || // \r = 13
18                (currentChar >= 0x20 && currentChar <= 0xD7FF) ||
19                (currentChar >= 0xE000 && currentChar <= 0xFFFD) ||
20                (currentChar >= 0x10000 && currentChar <= 0x10FFFF))
21            {
22                //Valid character
23            }
24            else
25                return false;
26        }
27    }
28    catch
29    {
30        return false;
31    }
32    return true;
33}
34

Use CSS to AutoSize a DIV

By Brian Pautsch – 8/11/2008. Posted to Code Snippets.

There are often cases where you want to display content in a div, but a fixed height won't work. It the height is too little, content is cut off or you need a vertical scrollbar (by setting the overflow value). If the height is too much, you'll have a lot of whitespace. The example below shows you how to easily create a div that autosizes based on the content.
1//HTML:
2<div id="outerDiv" class="autosize">
3    <div id="innerDiv" runat="server" style="display: block">
4        //Content...
5    </div>
6</div>
7
8//CSS:
9#outerDiv
10{
11    min-height: 200px; 
12}
13
14div.autosize { display: table; width: 1px; }
15div.autosize > div { display: table-cell; }

Access ScriptManager in a Master Page from Content Page

By Brian Pautsch – 6/12/2008. Posted to Code Snippets.

I recently had to access the ScriptManager in a Master Page from one of the Content Pages.
I first tried to perform a FindControl(), but there's a much easier way.
There is a static method in the ScriptManager class called "GetCurrent()" which provides access to the current instance of the ScriptManager.


//Extend script manager timeout to 10 minutes

ScriptManager.GetCurrent(this).AsyncPostBackTimeout = 600;

How to check for hexidecimal characters

By Brian Pautsch – 3/28/2008. Posted to Code Snippets.

If you haven't come across it yet, hexidecimal characters are not allowed in XML documents and cause problems when trying to display or work with them. When working with 3rd party data in XML (not received via a web service), it's always a good idea to validate the data. If you see an error like "hexidecimal value 0x04, is an invalid character, Line 1 Position 20154755", your problem is the data in the XML document. We recently came across this issue and created a simple method to check for valid characters:

Be sure to check out related blog: How to validate strings for XML

1private bool IsValidString(string input)
2{
3    try
4    {
5        char[] values = input.ToCharArray();
6        foreach (char c in values)
7        {
8            //Get the integral value of the character
9            int value = Convert.ToInt32(c);
10            //Valid character (space -> tilde) see: http://www.asciitable.com
11            if (value < 32 || value > 126)
12                return false;
13        }
14    }
15    catch
16    {
17        return false;
18    }
19    return true;
20}

Safely restart an ASP.NET remotely

By Brian Pautsch – 2/12/2008. Posted to Code Snippets.

Every once in awhile, an ASP.NET website may need to be restarted. There are a few ways to do this: kill the worker process (too forceful), restart IIS (restarts all websites) or modify the web.config (best choice). Instead of FTP'ing the web.config down and back up or logging onto the server to update the web.config, why not create a web page that allows you to easily update the "last write date" on the file. The .NET Framework monitors website files and when the web.config write date changes, it automatically restarts that website. Here's code you can drop into an ASP.NET web page to accomplish this:

1<%@ Page Language="C#" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5<script runat="server">
6    protected void Page_Load(object sender, EventArgs e)
7    {
8        lblMessage.Text = "";
9    }
10
11    protected void btnRestart_Click(object sender, EventArgs e)
12    {
13        if (txtPassword.Text.Trim().ToUpper() ==
14            System.Configuration.ConfigurationManager.AppSettings["ResetSitePassword"].ToString().Trim().ToUpper())
15        {
16            string webConfigPath = Server.MapPath("~/Web.config");
17            System.IO.File.SetLastWriteTime(webConfigPath, DateTime.Now);
18            Session.Abandon();
19            Response.Redirect("/");
20        }
21        else
22            lblMessage.Text = "Invalid password";
23    }
24</script>
25
26<html xmlns="http://www.w3.org/1999/xhtml">
27<head runat="server">
28    <title>Restart Website</title>
29</head>
30<body>
31    <form id="aspnetForm" runat="server">
32        Password:
33        <asp:TextBox ID="txtPassword" runat="server" TextMode="Password"></asp:TextBox>
34        <asp:Button ID="btnRestart" runat="server" Text="Restart" OnClick="btnRestart_Click">
35        </asp:Button>
36        <asp:Label ID="lblMessage" runat="server" ForeColor="Red"></asp:Label>
37    </form>
38</body>
39</html>

How to Communicate between ASP.NET and Flash

By Brian Pautsch – 12/18/2007. Posted to Code Snippets.

Ever wonder how to send data back and forth between ASP.NET and Flash?

About a year ago, we designed and built the DIY Floor Plan website (http://www.diyfloorplan.com). We needed the ability to send data between the Flash Floor Plan Designer and the ASP.NET web pages that saved the data to the database. We wanted the floor plan designer to be as "dumb" as possible...simply design the floor plan and allow the ASP.NET application manage the data. Here's some quick code snippets that will show you how to do it very easily.

ViewFloorPlan.aspx
This page displays the public, non-editable version of the floor plan. The important thing here is that we put the Floor Plan GUID in a Flash Parameter. We use a GUID to prevent users from seeing floor plans that are not publicly available by the floor plan administrator. The Flash application uses the GUID as the key to communicate with the ASP.NET application.

1<script type="text/javascript">
2    var so = new SWFObject("/flash/map_client.swf", "map_client", "775", "650", "6", "#ececec");
3    so.addParam("menu", "false");
4    so.addParam("quality", "high");
5    so.addParam("wmode", "transparent");
6    so.addParam("allowScriptAccess", "sameDomain");
7    so.addParam("movie", "/flash/map_client.swf");
8    so.addParam("bgcolor", "#ffffff");
9    so.addParam("FlashVars", "FloorPlanGUID=<% GetFloorPlanGUID(); %>");
10    so.write("flashcontent1");
11</script>
FlashGetData.aspx
This page is used by the Flash application to get data. The ASPX portion of this web page has no HTML or controls. When processing the Flash application's request, we output the data it needs in the HTML in a name-value pair. A little explanation...this page is called for the floor plan XML or an individual booth's details (name, address, etc.). After calling the database to get the data, it's written to the output HTML as field=value.

1public partial class FlashGetData : System.Web.UI.Page
2{
3protected void Page_Load(object sender, EventArgs e)
4    {
5       if (Request.QueryString["Mode"] != null)
6        {
7            try
8 { 9 //Extract mode
10 Enums.ModeEnum mode =
(Enums.ModeEnum)int.Parse(Request.QueryString["Mode"].ToString()); 11
12 //Process based on mode
13 DataSet ds = null; 14 DataRow row; 15 if (mode == Enums.ModeEnum.RequestFloorPlan) 16 { 17 //Extract Querystring parameters
18 string floorPlanGUID = Request.QueryString["FloorPlanGUID"].ToString(); 19
20 //Get the data
21 ds = FloorPlans_BLL.SelectFloorPlansByFloorPlanGUID(new Guid(floorPlanGUID)); 22 row = ds.Tables[0].Rows[0]; 23 Response.Write("FloorPlanXML=" + row["FloorPlanXML"].ToString()); 24 } 25 else if (mode == Enums.ModeEnum.RequestCompanyDetails) 26 { 27 //Extract Querystring parameters
28 string floorPlanGUID = Request.QueryString["FloorPlanGUID"].ToString(); 29 string boothID = Request.QueryString["BoothID"].ToString(); 30
31 //Get the data
32 ds = Companies_BLL.SelectCompaniesByFloorPlanIDBoothID(
new Guid(floorPlanGUID), boothID); 33 Response.Write("CompanyDetails=" + BuildCompanyDetails(boothID, ds)); 34 } 35 } 36 catch (Exception ex) 37 { 38 Helpers.ProcessException(ex); 39 } 40 } 41 } 42}
FlashSaveData.aspx
This page is used in the administration area. Again, the ASPX portion of this web page has no HTML or controls.
The Flash movie executes a command like: xmlDoc.sendAndLoad("FlashSaveData.aspx?FloorPlanGUID=xxx-xxx-xxx-xxx", returnXML, "POST");
The important point of this code is Line 19. The Flash application posts data in the Request stream.

1public partial class FlashSaveData : System.Web.UI.Page
2{
3protected void Page_Load(object sender, EventArgs e)
4    {
5        //The Flash movie executes a command like:
6 //xmlDoc.sendAndLoad("FlashSaveData.aspx?FloorPlanGUID=xxx-xxx-xxx-xxx",
returnXML, "POST");
7
8 XmlDocument doc = null; 9 FloorPlans floorplans = null; 10 FloorPlanCompanies fpc = null; 11 DataSet ds = null; 12 try
13 { 14 if (Request.QueryString["FloorPlanGUID"] != null) 15 { 16 //Extract GUID and XML
17 string floorPlanGUID = Request.QueryString["FloorPlanGUID"].ToString(); 18 doc = new XmlDocument(); 19 doc.Load(Request.InputStream); 20
21 //Get the FloorPlan row
22 ds = FloorPlans_BLL.SelectFloorPlansByFloorPlanGUID(new Guid(floorPlanGUID)); 23 DataRow row = ds.Tables[0].Rows[0]; 24
25 //Build FloorPlans object
26 floorplans = new FloorPlans(); 27 floorplans.FloorPlanID = Int32.Parse(row["FloorPlanID"].ToString()); 28 floorplans.FloorPlanGUID = new Guid(row["FloorPlanGUID"].ToString()); 29 floorplans.UserID = Int32.Parse(row["UserID"].ToString()); 30 floorplans.Title = row["Title"].ToString(); 31 floorplans.URL = row["URL"].ToString(); 32 floorplans.FloorPlanXML = doc.InnerXml; 33 floorplans.Active = (bool)row["Active"]; 34 floorplans.RewriterID = Int32.Parse(row["RewriterID"].ToString()); 35
36 //Make sure all booths are now in the database
37 XmlNodeList objNodes = doc.SelectNodes("./floorplan/booths/boothtxt"); 38 foreach (XmlNode objNode in objNodes) 39 { 40 fpc = new FloorPlanCompanies(); 41 fpc.FloorPlanID = Int32.Parse(row["FloorPlanID"].ToString()); 42 fpc.BoothID = objNode.InnerXml; 43 fpc.CompanyID = 0; 44 FloorPlanCompanies_BLL.SaveFloorPlanCompanies(fpc, false, null); 45 } 46
47 //Save to database
48 FloorPlans_BLL.UpdateFloorPlans(floorplans); 49 } 50 else
51 throw new Exception("FloorPlanGUID missing"); 52 } 53 catch (Exception ex) 54 { 55 Helpers.ProcessException(ex); 56 } 57 finally
58 { 59 if (ds != null) 60 { 61 ds.Dispose(); 62 ds = null; 63 } 64 fpc = null; 65 floorplans = null; 66 doc = null; 67 } 68 } 69}

How to make an AJAX Postback with JavaScript

By Brian Pautsch – 12/3/2007. Posted to Code Snippets.

Recently, we were working on a project that required us to make an AJAX postback with a table cell (TD) onclick event. We were "forced" to do this because the webpage designer wanted the search results displayed in a table and the TD's had onmouseover, onmouseout and onmouseclick events. The way he designed it was very nice and we didn't want to change it because AJAX for .NET didn't natively support the TD click event.

We quickly searched the web for an answer and couldn't find anything. Over the past few months many others asked how to do it too, but nobody could provide an answer. It's really not that difficult...you just need to be a little creative and think how AJAX works in ASP.NET.

In our project, we were binding location search results to a Repeater. In the onclick event, we added code to make a call to JavaScript function "makeAJAXPostback" and passed the ID. Originally, we tried to make a call to __doPostBack, but that forces a full page postback:

1<asp:Repeater ID="rptSearchResults" runat="server">
2    <ItemTemplate>
3        <table width="100%" border="0" cellpadding="0" cellspacing="4">
4            <tbody>
5                <tr>
6                    <td class="agentbox" onmouseover="style.backgroundColor='#e0e8f3';"
                              onmouseout="style.backgroundColor='#f1f1f1';"
7 onclick="makeAJAXPostback('<%# DataBinder.Eval(Container.DataItem, "ID")%>')"> 8 <%# DataBinder.Eval(Container.DataItem, "DisplayName")%> 9 <br /> 10 <%# DataBinder.Eval(Container.DataItem, "Address1")%> 11 <br /> 12 <%# DataBinder.Eval(Container.DataItem, "City")%> 13 <br /> 14 <%# DataBinder.Eval(Container.DataItem, "StateIDCode")%> 15 <%# DataBinder.Eval(Container.DataItem, "Zip")%> 16 <br /> 17 <%# DataBinder.Eval(Container.DataItem, "Phone")%> 18 </td> 19 </tr> 20 </table> 21 </ItemTemplate> 22</asp:Repeater> 23
At the bottom of the page, we added a the "makeAJAXPostback" function.
We also added a hidden field and a hidden HTML submit button:

1            <input type="submit" id="btnTDClicked" name="btnTDClicked" style="display: none" />
2            <input type="hidden" id="hidTDClickID" name="hidTDClickID" />
3        </ContentTemplate>
4    </asp:UpdatePanel>
5    <script type="text/javascript">
6        function makeAJAXPostback(TDClickID)
7        {
8            document.forms[0].hidTDClickID.value = TDClickID;
9            document.forms[0].btnTDClicked.click();
10        }
11    </script>
12</asp:Content>
13
When the TD cell is clicked, the "makeAJAXPostback" function is called, the ID is put in the hidden field and the hidden button is clicked. Because the AJAX Toolkit handles all form postbacks, the button click is automatically made via AJAX.

All that's left is to handle the postback on the server. In Page_Load, we simply check if the hidden field is populated and process accordingly:

1//Handle TD Clicked Event when user clicks search results2if (Request.Form["hidTDClickID"] != null &&
3    Request.Form["hidTDClickID"].ToString() != "")
4    TDClicked(int.Parse(Request.Form["hidTDClickID"].ToString()));

Convert Plain Text to MD5 Hash

By Brian Pautsch – 11/20/2007. Posted to Code Snippets.

Nothing groundbreaking here, but if you need to know how to convert plain text to an MD5 Hash, here you go:

1using System;
2using System.Security.Cryptography;
3using System.Text;
4
5public static string ConvertToMD5(string plainText) 6{ 7 byte[] input = Encoding.UTF8.GetBytes(plainText); 8 byte[] output = MD5.Create().ComputeHash(input); 9 return Convert.ToBase64String(output).Trim(); 10}

/html>

Enable File Upload on an AJAX Webpage

By Brian Pautsch – 11/8/2007. Posted to Code Snippets.

File uploads do not work when doing async postbacks due to security restrictions. Because of this, we have to add a PostBackTrigger. PostbackTriggers enable controls inside an UpdatePanel to cause a postback instead of performing an asynchronous postback. Here's a code snippet that shows how to accomplish this.
 
<asp:Content ID="Content1" ContentPlaceHolderID="cphContent" runat="Server">
    <asp:UpdatePanel ID="UpdatePanel1" runat ="server">
        <Triggers>
            <asp:PostBackTrigger ControlID="imgbtnUpload" />
        </Triggers>
         <ContentTemplate>
              <asp:FileUpload ID="txtFile" runat ="server" />
            <asp:ImageButton ID="imgbtnUpload" runat="server" ImageUrl="~/Common/Images/upload.gif" OnClick="imgbtnNext_Click" />
        </ContentTemplate>
    </ asp:UpdatePanel>
</ asp:Content>

By adding the PostbackTrigger, you can mix controls that make AJAX calls with controls that require the postback and maintain the good user experience.

PayPal PDT Sandbox Setup

By Brian Pautsch – 8/1/2007. Posted to Code Snippets.

I recently implemented a PayPal checkout solution using Payment Data Transfer (PDT) to retrieve the transaction details. Testing the transaction process required using PayPal Sandbox, which I have used before and for which I already had my acccount set up. But when my customer wanted to do some testing, I had them set up their own Sandbox account, and was reminded that the initial setup is not simple. Eventually, I had to provide step by step instructions to get them up and running correctly.

Here are those instructions for anyone needing to go through this for the first time:
1. Go to https://developer.paypal.com/ and create a new PayPal Developer account. After confirming the account, log in and you will see:
    - Tab for Test Accounts – this is where you create Buyer and Seller accounts. A Seller account provides you with a fake online store, and a Buyer account allows you to make fake purchases from that store.
    - Tab for Test Email – this is where all the order/payment emails are sent during test purchases. The emails are contained within the Sandbox environment, not sent to external email accounts.
    - Tab for API Credentials – for a PDT application, ignore this tab completely. There is an Identity Token here, but it is not the one needed for the "PayPalPDTID” in the web.config. There is also a seller password here, but it is not the one you will use during testing.

2. In the upper right corner, click “Enter Sandbox”.
    - Log in to Sandbox using the Seller Test Account credentials. For PDT to work, go to “Profile” tab, then “Selling Preferences”, then “Website Payment Preferences” and confirm you have the following settings:
    “Auto Return for Website Payments” is on, return URL is set to http://www.yoursite.com/PDTHandler.aspx (or whatever page you use to process the transaction details.
    “Payment Data Transfer” is on. Note that this is where you get the Identity Token that should be used in the web.config.

Back in the project, you need to open the web.config and check these settings:
<appSettings>
	<add key="RootURL" value="http://localhost:xxxxx/ProjectName/"/>
		   
	<!-- Sandbox Settings -->
	<add key="PayPalServer" value="https://www.sandbox.paypal.com/cgi-bin/webscr"/>
	<add key="UseSandbox" value="true"/>
	<add key="PayPalEmailAddress" value="Seller email address used to login to Sandbox"/>
	<add key="PayPalPDTID" value="Identity Token from the Website Payment Preferences"/>		
</appSettings>

You are finally ready to run the project and make a purchase. When it redirects to PayPal, make sure it goes to https://www.sandbox.paypal.com/cgi-bin/webscr and login using the Buyer Test Account credentials. Complete the purchase and wait for it to redirect back to the project. You should have a message page advising that the transaction failed or was completed.

Finally, you can go back to https://developer.paypal.com/, enter Sandbox, login using the Seller credentials, and under My Account - History, see a report of all the transactions posted.

Use Dynamic Connection Strings MDAAB

By Brian Pautsch – 7/4/2007. Posted to Code Snippets.

I recently came across a situation where I needed to pass the Microsoft Data Access Application Blocks a dynamic connection string. Out of the box, the DAAB does not support this.

Solution: Create a simple method that accepts a connection string and return a Database object.

Code Before:
Database db = DatabaseFactory.CreateDatabase();

Code After:
Database db = CustomDatabaseFactory.CreateDatabase(connstring);


Class Code:
1using System;
2using System.Collections.Generic;
3using System.Data.Common;
4using System.Text;
5using Microsoft.Practices.EnterpriseLibrary.Data;
6namespace Satisfyd.DataAccessLayer
7{
8//This class is used to dynamically set the connection string
9//while using the Microsoft Data Application Blocks
10publicstaticclass CustomDatabaseFactory 11 { 12staticreadonly DbProviderFactory dbProviderFactory = 13 DbProviderFactories.GetFactory("System.Data.SqlClient"); 1415publicstatic Database CreateDatabase(string connectionString) 16 { 17returnnew GenericDatabase(connectionString, dbProviderFactory); 18 } 19 } 20}

Re-Enable A Disabled SQL Server 2005 Service Broker

By Brian Pautsch – 6/27/2007. Posted to Code Snippets.

If you are caching data using SQL Cache Dependency with the SqlCacheDependency parameter set to "CommandNotification", and then restore or detach/attach your database (say, during a deployment), you will likely see this error:

"The SQL Server Service Broker for the current database is not enabled, and as a result query notifications are not supported. Please enable the Service Broker for this database if you wish to use notifications."

This is caused by the fact that the service broker is disabled automatically during these operations. To re-enable it, you need to run the following:

   ALTER DATABASE YOUR_DATABASE SET ENABLE_BROKER
 
 

Acropolis: The Future Of Windows Client Development

By Brian Pautsch – 6/21/2007. Posted to Code Snippets.

Microsoft has released the Acropolis CTP, a set of tools and components that help developers quickly assemble applications from loosely-coupled parts and services. With Acropolis you will be able to:

  • Quickly create WPF enabled user experiences for your client applications.
  • Build client applications from reusable, connectable, modules that allow you to easily create complex, business-focused applications in less time.
  • Integrate and host your modules in applications such as Microsoft Office, or quickly build stand-alone client interfaces.
  • Change the look and feel of your application quickly using built-in themes, or custom designs using XAML.
  • Add features such as workflow navigation and user-specific views with minimal coding.
  • Manage, update, and deploy your application modules quickly and easily.

David Hill has put together a short video walkthrough of using Acropolis:

You can download the CTP here:

 

How to Add a Digg Link to Your Website

By Brian Pautsch – 6/3/2007. Posted to Code Snippets.

If you're not familiar with Digg.com, you might want to check it out.

What is Digg?
"Digg is a user driven social content website. Ok, so what the heck does that mean? Well, everything on Digg is submitted by our community (that would be you). After you submit content, other people read your submission and Digg what they like best. If your story rocks and receives enough Diggs, it is promoted to the front page for the millions of visitors to see.

What can you do as a Digg user? Lots. Every person can digg (help promote), bury (help remove spam), and comment on stories... you can even Digg and bury comments you like or dislike. Digg also allows you to track your friends' activity throughout the site — want to share a video or news story with a friend? Digg it!"

I have been visiting Digg at least 2-3 times per week to read the quick posts. I usually jump directly to "Top in 24 Hours" page. This page usually has some really interesting links: http://www.digg.com/news/popular/24hours

If you decide to post a link, be sure your server can handle the hits. Everyday, sites crash due to too many hits too fast from Digg users. Or if your hosting provider has limits on bandwidth, you might lose your account all together. Fortunately, we have our own servers and can handle this type of traffic.

Back to the topic of this blog...if you decide to post a link on Digg, here's the snippet of code you need to add to your website to add the Digg Link to your website:

<script type="text/javascript">
    digg_url = "digg url to your link";
</script>
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script>

For example:
<script type="text/javascript">
    digg_url = "http://digg.com/software/20_Promo_Code_SGMAY07_good_for_1_week";
</script>
<script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script>

results in this:

unescape() in Code Behind

By Brian Pautsch – 5/22/2007. Posted to Code Snippets.

Ever have the need to unescape a string in your code-behind? Here's how:

value = Microsoft.JScript.GlobalObject.unescape(value);

Just remember to add a reference to Microsoft.JScript in your project.
You now have access to all javascript functions in your code-behind.

Automating Database Maintenance in SQL Server 2005 Express

By Brian Pautsch – 2/21/2007. Posted to Code Snippets.

When building highly scalable applications, you need a powerful database. My database of choice right now is SQL Server 2005. Since a full SQL Server license costs a few thousand dollars per processor, I use SQL Server Express. Why not...it's free! It's basically the same thing as the full blown SQL Server 2005, except there are some limitations on memory, database capacity and other things I will not hit with the websites I build on the side. It also doesn't allow you Import/Export data which is a vey useful feature. That's OK, we can script our database updates. And finally, it doesn't include scheduled maintenance. This is not good. All websites and databases MUST be backed up daily in case of a disaster.

So how do we implement this?
I did a quick search on Google and found the following webpage:
http://www.sqldbatips.com/showarticle.asp?ID=27

Download SQL script

Basically, it's a SQL script that does the maintenance tasks for you. Simply specify the parameters based on your needs and schedule it to run with Windows Task Scheduler. That's it!

Example execute call
This call executes a Full Database Backup of all user databases to c:\backups.
It also verifies the backups and reports to c:\reports.
It keeps the backups for 2 weeks and reports for 1 week

  exec expressmaint
      @database      = 'ALL_USER', 
      @optype         = 'DB',
      @backupfldr    = 'c:\backups',
      @reportfldr      = 'c:\reports',
      @verify          = 2,
      @dbretainunit  = 'weeks',
      @dbretainval   = 1,
      @rptretainunit  = 'weeks',
      @rptretainval   = 1,
      @report          = 1


Example Scheduled Task
On my server, I have it scheduled with the following parameters. It's set to run everyday at 3am.

Run: "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\SQLCMD.EXE" -S.\SQLExpress -i"D:\DBBackups\UserFullBackup.sql"

Start in: "C:\Program Files\Microsoft SQL Server\90\Tools\Binn"

Additional comments
1. When I ran the script for the first time, I received the following error:
SQL Server blocked access to procedure 'sys.sp_OACreate' of component 'Ole Automation Procedures' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Ole Automation Procedures' by using sp_configure. For more information about enabling 'Ole Automation Procedures', see "Surface Area Configuration" in SQL Server Books Online.

To resolve it, run the following SQL commands:
USE master
GO
sp_configure
'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO

2. I then received error:
SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'xp_cmdshell' by using sp_configure. For more information about enabling 'xp_cmdshell', see "Surface Area Configuration" in SQL Server Books Online.

To resolve it, run the following SQL commands:
USE master
GO
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'xp_cmdshell', 1
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'show advanced options', 0
GO

SQL Server 2005 - Generate INSERT statements for easy migrations

By Brian Pautsch – 12/12/2006. Posted to Code Snippets.

I often work in a local environment and later need to migrate data to a remote database server. If the ports are open on the remote server, I can just export the data. Often this is not the case. In the past, I have either
- Export the data, FTP it to the other location and import the data (what a pain!)
- Used code I wrote to export the data to INSERT statements, copy/paste text to other location and execute scripts (not too bad)

I was looking for an easier approach and came across Narayana Vyas Kondreddi's website. He has written a ton of code (VB and SQL) to do a lot of the everyday things we do.

Here's a link to a "Procedure to script your data (to generate INSERT statements from the existing data)":
http://vyaskn.tripod.com/code.htm#inserts

It's great. It installs in the master database and is available to all users for all databases.
It even has options to filter results, omit certain data types, get only n rows, and much more.
Be sure to check it out for yourself.

In case the site ever shuts down, here's a link to the SQL 2005 script.

How To Get Around Having To Click Flash Movies

By Brian Pautsch – 11/29/2006. Posted to Code Snippets.

If you use Internet Explorer, I’m sure you’re just as annoyed as me with the need to click a Flash movie once just to activate it. Not sure what I’m talking about? Check out this website I built: http://www.coyledevelopment.com

Notice the Flash object is disabled (it runs, but you can’t interact with it) and your cursor has a little message that states “Click to activate and use this control”. Once you click it, it becomes “unlocked” and you can use it. What a pain, right? If the Flash object does any kind of posting back to the webpage and re-renders itself, you’ll have to click it again…meaning, your choice to activate it isn’t “saved” during your session.

Why must we deal with this? It’s because of a dispute between Microsoft and Eolas. Eolas owns the patent to the technology for rendering plug-ins in web browsers. Microsoft must license the technology in order to use it in IE. They don’t want to so they added this annoyance to better their case. Read more at: http://en.wikipedia.org/wiki/Eolas

So how can I get around it? It’s easy now thanks to deconcept and SWFObject.
1. Download the SWFObject Javascript file

2. Include the swfobject.js Javascript file and write a small amount of Javascript on your page to embed your Flash movie. Here is an example showing the minimum amount of code needed to embed a Flash movie:

<script type="text/javascript" src="swfobject.js"></script>  
<div id="flashcontent">
  This text is replaced by the Flash movie.
</div>
<script type="text/javascript">
   var so = new SWFObject("movie.swf", "mymovie", "200", "100", "7", "#336699");
   so.write("flashcontent");
</script>

This is just the basic explanation. You might want to know more about required parameters versus optional parameters or how to pass variables into the movie. For this information, visit their website to learn more.

Gmail Spam Trick

By Brian Pautsch – 11/15/2006. Posted to Code Snippets.

I saw this forum entry on digg.com and had to share...pretty tricky:

When you give your email address to a website, you hope that they don't sell or trade your address to a bunch of spammers. Well if they do, here is a simple way to see what sites are responsible for what particular piece of email. This requires you have a Gmail account.

If your Gmail login name was mailto:username@gmail.comand you went to samplesite.com to fill out a registration form, instead of just entering mailto:username@gmail.comas your email, enter it as mailto:username+samplesitecom@gmail.cominstead. When Gmail sees a "+" in an email address, it uses all the characters to the left of the plus sign to know who to send it to. In this example it would still send it to mailto:username@gmail.com.

Now whats cool is if you search Gmail for username+samplesitecom, you will see all massages that were sent to that email address.

To see who is responsible for sending a specific message click the Show Details link and you will see the complete address.

How to Add a WinForm DataGridView Header CheckBox

By Brian Pautsch – 10/10/2006. Posted to Code Snippets.

A recent project required that we figure out how to add a "Select All" checkbox to the header column header of a DataGridViewCheckBoxColumn Windows Forms. After searching the web for possible solutions, it became clear that the actual control cound not be added dynamically. The best approach we could find was to paint a checkbox image into the header and respond to the DataGridView's "ColumnHeaderMouseClick" event. Here's the solution in detail:

Download source code



1. Create a Resource File and add in the two attached images. When I dragged them in, they were renamed to “_checked” and “_unchecked”.

2. Declare a “Select All” private variable.
1privatebool _selectAll = false;
3. Wherever you bind your DataGridView (I did in Page_Load for this example), add in the checkbox column (unless you already have it in your design view).

1private void Form1_Load(object sender, EventArgs e)
2{
3    try
4 { 5 //Bind XML dataset to DataGridView
6 DataSet ds = new DataSet(); 7 ds.ReadXml(_xmlFilePath); 8 dataGridView1.DataSource = ds.Tables[0]; 9 //Add the checkbox column
10 dataGridView1.Columns.Insert(0, 11 new DataGridViewCheckBoxColumn()); 12 } 13 catch (Exception ex) 14 { 15 MessageBox.Show("Exception: " + ex.ToString()); 16 } 17}
4. Create the CellPainting Event.

1privatevoid dataGridView1_CellPainting(object sender, 
2    DataGridViewCellPaintingEventArgs e)
3{
4    //Is this the checkbox column header?
5 if (e.RowIndex == -1 && e.ColumnIndex == 0) 6 { 7 try
8 { 9 //Erase the cell
10 using (Brush backColorBrush = 11 new SolidBrush(e.CellStyle.BackColor)) 12 { 13 e.Graphics.FillRectangle(backColorBrush, e.CellBounds); 14 } 15
16 //Draw 1 bottom line...
17 e.Graphics.DrawLine(Pens.DarkGray, e.CellBounds.Left, 18 e.CellBounds.Bottom - 1, e.CellBounds.Right, e.CellBounds.Bottom - 1); 19 //Draw 2 top lines...
20 e.Graphics.DrawLine(Pens.DarkGray, e.CellBounds.Left, 21 e.CellBounds.Top, e.CellBounds.Right, e.CellBounds.Top); 22 e.Graphics.DrawLine(Pens.White, e.CellBounds.Left, 23 e.CellBounds.Top + 1, e.CellBounds.Right, e.CellBounds.Top + 1); 24 //Draw right line...
25 e.Graphics.DrawLine(Pens.DarkGray, e.CellBounds.Right - 1, 26 e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom); 27 //Draw left line...
28 e.Graphics.DrawLine(Pens.White, e.CellBounds.Left, 29 e.CellBounds.Top, e.CellBounds.Left, e.CellBounds.Bottom); 30
31 //Get the image from the resource file
32 Image imgChecked = (Image)Resource1._checked; 33 Image imgUnchecked = (Image)Resource1._unchecked; 34
35 //Determine paint coordinates
36 int X = e.CellBounds.Left + 37 ((e.CellBounds.Width - imgChecked.Width) / 2) - 1; 38 int Y = e.CellBounds.Top + 39 ((e.CellBounds.Height - imgChecked.Height) / 2) - 1; 40
41 //Draw checkbox in header
42 if (_selectAll) 43 e.Graphics.DrawImage(imgChecked, X, Y); 44 else
45 e.Graphics.DrawImage(imgUnchecked, X, Y); 46
47 //Set event as handled
48 e.Handled = true; 49 } 50 catch
51 { 52 //Handle exception
53 } 54 } 55}
5. Handle the Select All click event.

1privatevoid dataGridView1_ColumnHeaderMouseClick(object sender, 
2    DataGridViewCellMouseEventArgs e)
3{
4    if (e.ColumnIndex == 0)
5    {
6        _selectAll = !_selectAll;
7        for (int i = 0; i < dataGridView1.Rows.Count; i++)
8        {
9            dataGridView1.Rows[i].Cells[0].Value = _selectAll;
10        }
11    }
12}

Get Current Page's HTML (C#)

By Brian Pautsch – 6/15/2006. Posted to Code Snippets.

I was working on a project where I needed to get the current page's HTML. I searched all over the Internet and could not find anything. Then I thought about the Page's built-in methods...Render! Here's how you get it:

1sw = new StringWriter();
2htmltw = new HtmlTextWriter(sw);
3base.Render(htmltw);
4StringBuilder html = sw.GetStringBuilder();
And be sure to drop this code in the "OnPreRenderComplete" method (you'll need to create an override in your code-behind).

Well that was easy enough, huh?

Enumerate An Enumeration

By Brian Pautsch – 4/6/2006. Posted to Code Snippets.

Enumerations can be a great way to store a number of named constants. Have you ever had the need to display all of the string values of an enumeration? This code snippet show you how to load a dropdownlist of car makes:
1private void LoadCarMakes()
2{
3 foreach (CarMakes carmake in GetEnumValues(typeof(CarMakes)))
4 {
5   ddlCarMakes.Items.Add(carmake);
6 }
7}
8private static System.Enum[] GetEnumValues(Type enumType)
9{
10 if (enumType.BaseType == typeof(System.Enum))
11 {
12  System.Reflection.FieldInfo[] fi = enumType.GetFields(
BindingFlags.Static | BindingFlags.Public); 13 System.Enum[] values = new System.Enum[fi.Length]; 14 for (int iEnum = 0; iEnum < fi.Length; iEnum++) 15 { 16 values[iEnum] = (System.Enum)fi[iEnum].GetValue(null); 17 } 18 return values; 19 } 20 else 21 { 22 throw new ArgumentException("enumType parameter is not a System.Enum"); 23 } 24}

Randomize your data with ease - SQL Server

By Brian Pautsch – 3/21/2006. Posted to Code Snippets.

Often, I have the need to randomize what's presented to the user. For a test taking application I wrote, each student's test questions had to be randomized (helps prevent cheating). For a community website I built, the website's homepage sponsors had to be randomized each time the page was displayed. I've seen people try to solve this all kinds of ways, but there's one VERY simply way to do it...use SQL Server GUIDs.

Let's say you have a table of Sponsors with a SponsorID (int, identity, primary key) and a SponsorImage (varchar(50)).




And you have the following sponsor data:




To get the data returned in a randomized order, run the following query:

SELECT *, NEWID() AS RandomNum
FROM Sponsors
ORDER BY RandomNum



As you can see, the GUID is auto-generated and when sorted upon gives a different sort order for the sponsors. Could it be any easier?

Hide your file downloads with binary streaming (C#)

By Brian Pautsch – 3/9/2006. Posted to Code Snippets.

Ever have the need to allow people to download files but don't want them to know the physical location? It's actually pretty easy...just put your files in a location not accessible to the web and stream them back to the user:

1private void SendFileToUser(string strFileFullPath)
2{
3 FileStream objFile = null;
4 BinaryReader objBR = null;
5 try 
6 { 
7  objFile = new FileStream(strFileFullPath, FileMode.Open); 
8  //Clear and change the response headers
9  Response.Clear();
10  Response.Charset = "";
11  Response.AddHeader("Content-disposition", 
12   "attachment; filename=" + 
13   Path.GetFileName(strFileFullPath));
14  //Stream the file down
15  objBR = new BinaryReader(objFile);
16  for (long l = 0; l < objFile.Length; l++)
17  {
18   Response.OutputStream.WriteByte(objBR.ReadByte());
19  }
20  objBR.Close();
21 }
22 catch (Exception ex)
23 {
24  throw new Exception("Exception: " + ex.Message);
25 }
26 finally
27 {
28  objBR = null;
29  objFile = null;
30 }
31}

Simple 3DES Encryption

By Brian Pautsch – 3/7/2006. Posted to Code Snippets.

Looking for a simple class to encrypt/decrypt strings such as passwords? Use this one...it's about as easy as it gets. And be sure to add a plain text phrase in your web.config (key="EncryptionKey") or hard code it in the app to make it impossible to find.

1using System;
2using System.Configuration;
3using System.Security.Cryptography;
4using System.Text;
5
6namespace com.BrianPautsch
7{
8 public class Cryptology
9 {
10  #region Encrypt
11  public static string Encrypt(string strPlainText)
12  {
13   TripleDESCryptoServiceProvider objDES = 
new TripleDESCryptoServiceProvider(); 14 MD5CryptoServiceProvider objMD5 =
new MD5CryptoServiceProvider(); 15 string strKey =
ConfigurationSettings.AppSettings["EncryptionKey"].ToString(); 16 objDES.Key = objMD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(strKey)); 17 objDES.Mode = CipherMode.ECB; 18 ICryptoTransform objDESEncrypt = objDES.CreateEncryptor(); 19 byte[] arrBuffer = ASCIIEncoding.ASCII.GetBytes(strPlainText); 20 return Convert.ToBase64String(objDESEncrypt.TransformFinalBlock(
arrBuffer, 0, arrBuffer.Length)); 21 } 22 #endregion 23 #region Decrypt 24 public static string Decrypt(string strBase64Text) 25 { 26 TripleDESCryptoServiceProvider objDES =
new TripleDESCryptoServiceProvider(); 27 MD5CryptoServiceProvider objMD5 =
new MD5CryptoServiceProvider(); 28 string strKey =
ConfigurationSettings.AppSettings["EncryptionKey"].ToString(); 29 objDES.Key = objMD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(strKey)); 30 objDES.Mode = CipherMode.ECB; 31 ICryptoTransform objDESEncrypt = objDES.CreateDecryptor(); 32 byte[] arrBuffer = Convert.FromBase64String(strBase64Text); 33 return ASCIIEncoding.ASCII.GetString(objDESEncrypt.TransformFinalBlock(
arrBuffer, 0, arrBuffer.Length)); 34 } 35 #endregion 36 } 37}

Hide DataGrid columns when they are dynamically generated

By Brian Pautsch – 3/6/2006. Posted to Code Snippets.

In a recent project I was working on, I needed to hide DataGrid columns in a table where the columns are dynamically generated. I thought I might be able to do it after binding to the DataGrid or during the DataBinding event, but no luck. It turns out you have to hide the cells in each row (including the header and footer) during the DataGrid's ItemDataBound event. By the way, in my example, I have an 'Edit' column in the first columns always...so remember that when you implement this solution.

1//Private constants/variables
2private const int mintNumColsToShow = 4;
3private int mintColCt = 0;
4
5//In some method...get data and bind to DataGrid
6objDataSvc = new DataSvc();
7DataTable objDT = null;
8objDT = objDataSvc.GetData();
9mintColCt = objDT.Columns.Count;
10dgResults.DataSource = objDT;
11dgResults.DataBind();
12
13//DataGrid's ItemDataBound event
14private void dgResults_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
15{
16 //Only show first n columns (including 'Edit')
17 if (mintColCt > mintNumColsToShow)
18 {
19  for (int intCt = mintNumColsToShow + 1; intCt <= mintColCt; intCt++)
20  {
21   e.Item.Cells[intCt].Visible = false;
22  }
23 }
24}

ASP.NET Custom Events - UserControls and Pages

By Brian Pautsch – 1/14/2006. Posted to Code Snippets.

I have been working on a project that uses a lot of UserControls. Often, multiple UserControls are loaded onto the same Page. And in some cases, what is processed on the PostBack of one userControl has a direct effect on the data displayed on the base page or another UserControl. The problem is that the Page and UserControls have already loaded and run through their Page_Load events. How do you handle this?

Answer: Custom Events
Actually, it's very simple. This article explains the most common scenario.

Users tab:


Tasks tab:


Problem: We have a base Page that holds two UserControls: Users and Tasks (see above). Our Users UserControl allows the users to be added/updated/deleted. The Tasks UserControl allows tasks to be created and assigned to users. When the Page loads for the first time, both UserControls are loaded for the first time and their dropdownlists are also loaded once (including the list of users on the Tasks UserControl).

On subsequent posts, the Page.IsPostBack property is checked and the trips to the database are saved. When a user is added on the Users UserControl, the cmdSave (Save button) event triggered and the user is added to the database...but it isn't reflected in the Tasks UserControl. Here's what needs to be done:

1. Users UserControl code - Declare a custom event (UCUpdated) and a generic method (RaiseUCUpdatedEvent) to call to fire the event. When appropriate, call RaiseUCUpdatedEvent. In the example below, a user is deleted so we must refresh the tasks' users dropdownlist otherwise we'll get referencial integrity errors when trying to assign a task to the deleted user.
1//Declare event2publicevent CommandEventHandler UCUpdated;
34//Method to fire event5privatevoid RaiseUCUpdatedEvent(string strMessage)
6{
7 CommandEventArgs args = new CommandEventArgs("UCUpdated", strMessage);
8 UCUpdated(this, args);
9}
1011//Sample code that triggers the event to fire12objDataSvc.DeleteProjectUsers(intProjectUserID);
13if (objDataSvc.ErrorCode == 0)
14{
15 lblMessage.Text = "Delete successful!";
16 RefreshDataGrid();
17 RaiseUCUpdatedEvent();
18}
19
2. Page code - In the Page_Load event, add an event handler for the Users UserControl UCUpdated event that references a private method. In the example below, we simply call the public method "Load ProjectUsers()" in the Tasks UserControl. This method clears the dropdownlist and loads the current project users (same method called in the Tasks UserControl's Page_Load when Page.IsPostBack is false.
1//Page_Load - add event handler2privatevoid Page_Load(object sender, System.EventArgs e)
3{
4 ucProjectUsers.UCUpdated += new System.Web.UI.WebControls.CommandEventHandler(ucProjectUsers_UCUpdated);
5}
67//Event handler8privatevoid ucProjectUsers_UCUpdated(object sender, System.Web.UI.WebControls.CommandEventArgs e)
9{
10 ucProjectTasks.LoadProjectUsers();
11}
12

Captcha - Implement into an ASP.NET application

By Brian Pautsch – 12/1/2005. Posted to Code Snippets.

Last night, I was over at my friend Jim's house working on some eBay and PayPal stuff. Jim was setting up a new eBay and PayPal account when he was presented with a Captcha image. He knew what he had to do, but asked me what it's purpose was. So it got me to thinking...what would it take to implement a Captcha image into an ASP.NET web application?

Download code

Background
Captcha - Wikipedia's Definition: (acronym for "completely automated public Turing test to tell computers and humans apart") is a type of challenge-response test used in computing to determine whether or not the user is human. The term was coined in 2000 by Luis von Ahn, Manuel Blum, and Nicholas J. Hopper of Carnegie Mellon University, and John Langford of IBM. A common type of captcha requires that the user type the letters of a distorted and/or obscured sequence of letters or digits that appears on the screen. Because the test is administered by a computer, in contrast to the standard Turing test that is administered by a human, a captcha is sometimes described as a reverse Turing test.



Basically, it's a distorted image of a sequence of letters and/or numbers. In order to proceed on a website, it requires the user to enter the value in a text box. Because the text is warped and the image area is filled with sprinkled pixels and shapes, it makes it almost impossible for a computer to read.

1. Create a class to generate the image - There are tons of examples online on how to create new bitmaps and add text and graphics. I used some of the experience I have with GDI and took some code from online examples. GDI isn't too difficult to code, but requires a good memory managment!

View the class code

2. Create an ASP.NET page to output the JPEG image - I searched all over for a way to load a binary output stream into the Image control, but no luck. It appears it is not possible without creating another page...so that's what I did. This page (CreateCaptcha.aspx) randomly creates a Captcha string, loads it into Session State (for verification later), instantiates the CaptchaImage class (which also creates the Captcha image), changes the Response ContentType to "image/jpeg" and writes the image to the Response output stream.

View the code behind

3. Create the webpage to display the Captcha image - The validation of the Captcha text is trivial, but the thing to learn here is how to load the image. In the ASPX HTML, you need to define the image tag like s <img src="CreateCaptcha.aspx"> When this is executed on the server, CreateCaptcha.aspx is invoked and the response is loaded into the image source.

View the ASPX code
View the code behind

PDFBox in .NET - Easily Convert PDFs to Text

By Brian Pautsch – 11/23/2005. Posted to Code Snippets.

I've been working with the Lucene.NET library for over a year now and am constantly finding new ways to integrate it into websites and applications. Several of my customers use a customized version of the Desktop Search application. I have also integrated the Website Spider for Lucene I created into many websites. For some time now, I've been looking for an open source approach to extracting the raw text from PDF files. I searched all over the place and have finally found it! PDFBox is an open source Java PDF library. The .NET version is available at IKVM.NET .

Download code (5.8 Mb, including all PDFBox DLLs)

To convert a PDF to text, it's this simple:
1using org.pdfbox.pdmodel;
2using org.pdfbox.util;
...
134 PDDocument objDocument = PDDocument.load(strFileName);
136 PDFTextStripper objTextStripper = new PDFTextStripper();
137 txtText.Text = objTextStripper.getText(objDocument);
...

It seems to run pretty fast, I extracted the text from a 2.3 Mb PDF in 5.2 sec.

.NET Zip Class (C#)

By Brian Pautsch – 11/5/2005. Posted to Code Snippets.

A couple weeks ago, a colleague and I were in need of a class that could handle compressing and extracting files. It had to handle "zip" and "jar" files and needed to interface with a .NET application. There were several COM components available, but we wanted a managed code solution. We searched through the web and there were a few example of developers "trying" to get it to work, but each example had a problem or two. Then we came across an article in MSDN Magazine: Using the Zip Classes in the J# Class Libraries to Compress Files and Data with C# . It was exactly what we were looking for and we implemented it very easily. So I decided to take an hour or so to create a simple application that uses the zip class.

Download application

Zip Class - View the class code

Zip Class Implementation -
View the form code-behind

Google Search in IE Context Menu

By Brian Pautsch – 10/22/2005. Posted to Code Snippets.

I spend a lot of time on Google and often jump to it from other sites to search for something I just read about. Wouldn't it be nice if I could just highlight text on a webpage, right-click and click "Search Google" from the context menu? Well now you can! About a year ago, I came across a Windows Tips and Tricks page and it explains a very easy way to do this.

Download code

To add "Google Search" to your Internet Explorer context menu (like Firefox has), here's how.
According to Microsoft, this method of adding context items should work as early as IE4.
Download the above code instead of creating the files from scratch (much easier).

Open notepad and paste the following code:
1Windows Registry Editor Version 5.00
2
3[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\Google As Is]
4@="C:\\google_context_noquote.js"
5"Contexts"=hex:10
6
7[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\Google w/Quotes]
8@="C:\\google_context_quote.js"
9"Contexts"=hex:10

You can change the paths to the js files if you want, just make sure you put the files where this says they are.
Save the file as google.reg, right-click it and select merge (or just double-click it).
Your registry was just updated to show two new entries in your IE context menu...now we need to create the js files.

Open notepad, paste the following code and save it as "google_context_noquote.js":
1<script language="javascript">
2// Get the window object where the context menu was opened.
3var oWindow = window.external.menuArguments;
4
5// Get the document object exposed through oWindow.
6var oDocument = oWindow.document;
7
8// Get the selection from oDocument.
9var oSelect = oDocument.selection;
10
11// Create a TextRange from oSelect.
12var oSelectRange = oSelect.createRange();
13
14// Get the text of the selection.
15var sNewText = oSelectRange.text;
16
17// Build Google QueryString
18var googleQ = "http://www.google.com/search?&q=" + sNewText;
19
20// Ask Google
21oWindow.open(googleQ);
22</script>

Open notepad, paste the following code and save it as "google_context_quote.js":
1<script language="javascript">
2// Get the window object where the context menu was opened.
3var oWindow = window.external.menuArguments;
4
5// Get the document object exposed through oWindow.
6var oDocument = oWindow.document;
7
8// Get the selection from oDocument.
9var oSelect = oDocument.selection;
10
11// Create a TextRange from oSelect.
12var oSelectRange = oSelect.createRange();
13
14// Get the text of the selection.
15var sNewText = oSelectRange.text;
16
17// Build Google QueryString
18var googleQ = "http://www.google.com/search?&q=%22" + sNewText + "%22";
19
20// Ask Google
21oWindow.open(googleQ);
22</script>

This will cause two new options to show up in the same menu that pops up when you have selected some text.
"Google As Is" sends a query to google with the selected text just as it is, no quotes.
"Google w/Quotes" does the same as above except it places quotes aroung the selected text.
You only need to restart your browser to get this to start working.

How to assign a default button to any control (C#)

By Brian Pautsch – 7/23/2005. Posted to Code Snippets.

When a web page has multiple buttons, you might want to change the default button in different cases. For example, imagine a web page that has a search area with datagrid results. The search area allows you to filter your search. When a result is selected to be edited, the fields that can be edited and a 'Save' button are displayed. If the 'Search' button is the default button, think about what happens when someone edits an item and hits 'Enter' while in an edit control field...'Search' is submitted, not 'Save'. Now you have to redo your changes and click 'Save'.

A lot of people post the following solution:

Page.RegisterHiddenField("__EVENTTARGET", "cmdSave")

For some reason, this doesn't always work. Even when 'cmdSave' is set a the '__EVENTTARGET', the page is submitted but the button's event isn't fired.

To resolve this, we need to submit the form ourselves. The following snippet of code shows how to assign submit buttons to controls (TextBoxes, DropDownLists, etc.). Once you implement the main method into your page's base class, it's only one line of code per control to set the default button.

1. Enum of Control Types - This enumeration lists the control types you can set a default button for. Add more as needed.
1public enum ControlTypes
2{
3 None = 0,
4 TextBox = 1,
5 DropDownList = 2,
6 CheckBox = 3,
7 ListBox = 4
8}
2. Method in Base Class to associate control to button
1public void SetDefaultButtonForControl(System.Web.UI.Page objPage,
2 Enums.ControlTypes intControlType, object objControl,
3 System.Web.UI.WebControls.Button objButton)
4{
5 string strScript = @"<SCRIPT language=""javascript"">
6  <!--
7  function catchKeyDown(btn, event)
8  {
9   if (document.all)
10   {
11    if (event.keyCode == 13)
12    {
13     event.returnValue=false;
14     event.cancel = true;
15     btn.click();
16    }
17   }
18   else if (document.getElementById)
19   {
20    if (event.which == 13)
21    {
22     event.returnValue=false;
23     event.cancel = true;
24     btn.click();
25    }
26   }
27   else if(document.layers)
28   {
29    if(event.which == 13)
30    {
31     event.returnValue=false;
32     event.cancel = true;
33     btn.click();
34    }
35   }
36  }
37  // -->
38  </SCRIPT>";
39 objPage.RegisterStartupScript("DefaultButtonForControl", strScript);
40
41 //Register with the control
42 switch (intControlType)
43 {
44  case Enums.ControlTypes.TextBox:
45  {
46   TextBox objTextBox = objControl as TextBox;
47   objTextBox.Attributes.Add("onkeydown", 
           "catchKeyDown(" + objButton.ClientID + ",event)"); 48 break; 49 } 50 case Enums.ControlTypes.DropDownList: 51 { 52 DropDownList objDropDownList = objControl as DropDownList; 53 objDropDownList.Attributes.Add("onkeydown",
             "catchKeyDown(" + objButton.ClientID + ",event)"); 54 break; 55 } 56 case Enums.ControlTypes.ListBox: 57 { 58 ListBox objListBox = objControl as ListBox; 59 objListBox.Attributes.Add("onkeydown",
             "catchKeyDown(" + objButton.ClientID + ",event)"); 60 break; 61 } 62 case Enums.ControlTypes.CheckBox: 63 { 64 CheckBox objCheckBox = objControl as CheckBox; 65 objCheckBox.Attributes.Add("onkeydown",
             "catchKeyDown(" + objButton.ClientID + ",event)"); 66 break; 67 } 68 } 69}
3. Implementation in webpage - This example sets the 'cmdSearch' button as the default button for the txtSearchLastName, cboSearchDistrict and cboSearchRole search controls. It also sets the 'cmdSave' button as the default button for the 'txtNewQ1', 'txtNewQ2', 'txtNewQ3', 'txtNewQ4' and 'txtComments' edit controls.
1private void Page_Load(object sender, System.EventArgs e)
2{
3 if (!Page.IsPostBack)
4 {
5   SetDefaultButtonForControl(this, 
6       Enums.ControlTypes.TextBox, txtSearchLastName, cmdSearch);
7   SetDefaultButtonForControl(this, 
8       Enums.ControlTypes.DropDownList, cboSearchDistrict, cmdSearch);
9   SetDefaultButtonForControl(this, 
10       Enums.ControlTypes.DropDownList, cboSearchRole, cmdSearch);
11   SetDefaultButtonForControl(this, 
12       Enums.ControlTypes.TextBox, txtNewQ1, cmdSave);
13   SetDefaultButtonForControl(this, 
14       Enums.ControlTypes.TextBox, txtNewQ2, cmdSave);
15   SetDefaultButtonForControl(this, 
16       Enums.ControlTypes.TextBox, txtNewQ3, cmdSave);
17   SetDefaultButtonForControl(this, 
18       Enums.ControlTypes.TextBox, txtNewQ4, cmdSave);
19   SetDefaultButtonForControl(this, 
20       Enums.ControlTypes.TextBox, txtComments, cmdSave);
21 }
22}

How to load an Excel spreadsheet into an ADO.NET DataSet

By Brian Pautsch – 6/7/2005. Posted to Code Snippets.

Have you ever wondered how to load a Microsoft Excel spreadsheet into an ADO.NET DataSet? Actually, it's pretty easy...only six lines of code! Now you can let people import data into your website in batches. Here's how:
1DataSet objDS = new DataSet();
2string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" + 
3 "Data Source=" + strFileName.Replace("\\", "\\\\") + ";" +
4 "Extended Properties=\"Excel 8.0;\"";
5objOLE = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", strConn);
6objOLE.Fill(objDS);
The above code snippet works great, but you must know the name of the worksheet (Sheet1 is the default for Excel). But what if you don't know the Worksheet name? What if you just want the first sheet? Then, you must use the Excel objects to get it:

1#region AnalyzeSpreadsheet
2public void AnalyzeSpreadsheet(string strFileName)
3{
4 //Excel variables
5 object con_true = true;
6 Excel.ApplicationClass objExcel = null;
7 Excel.Workbook objBook = null;
8 Excel.Worksheet objSheet = null; 
9 try
10 {
11 //Create new instance of Excel Application
12 objExcel = new Excel.ApplicationClass();
13 //Set some options
14 objExcel.DisplayAlerts = false;
15 objExcel.ScreenUpdating = false;
16 objExcel.Visible = false;
17 objExcel.UserControl = false;
18 //Open spreadsheet
19 objBook = objExcel.Workbooks.Open(strFileName, Type.Missing,
20 Type.Missing, Type.Missing, Type.Missing, Type.Missing,
21 Type.Missing, Type.Missing, Type.Missing, Type.Missing,
22 Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
23 //Find the 1st worksheet
24 objSheet = (Excel.Worksheet)objBook.Worksheets.get_Item(1); 
25 if (objSheet == null)
26 throw new Exception("Worksheet #1 not found!");
27 else
28 {
29 //Do something...
30 }
31 }
32 catch
33 {
34 //Handle exception
35 }
36 finally
37 {
38 ReleaseComObject(objSheet);
39 objSheet = null;
40 objBook.Close(con_true, strFileName, null);
41 ReleaseComObject(objBook);
42 objBook = null;
43 objExcel.Workbooks.Close();
44 objExcel.Application.Quit();
45 ReleaseComObject(objExcel);
46 objExcel = null;
47 }
48}
49#endregion
50#region ReleaseComObject
51private void ReleaseComObject(object o)
52{
53 Int32 i = 0;
54 Int32 j = 0;
55 try 
56 {
57 for (i = 1; i <= 
System.Runtime.InteropServices.Marshal.ReleaseComObject(o); i++) 58 { 59 j =
System.Runtime.InteropServices.Marshal.ReleaseComObject(o); 60 } 61 } 62 catch 63 { 64 } 65 finally 66 { 67 o = null; 68 } 69} 70#endregion

Email Address Validator (C#)

By Brian Pautsch – 5/30/2005. Posted to Code Snippets.

If you're building any kind of website that allows users to register, you're going to need an email validator. Some people recommend using a regular expression validator and that works well for most situations, but isn't foolproof. Below is a code snippet of a method that takes in an email address and returns a boolean value.

1public bool IsValidEmail(string strEmail)
2{
3 //Ensure some data is sent in
4 if (strEmail == null || strEmail.Length == 0)
5  return false;
6 //Ensure no spaces exist in the email address
7 if (strEmail.IndexOf(" ") > -1)
8  return false;
9 //Ensure ".@" isn't in the email address
10 if (strEmail.IndexOf(".@") > -1)
11  return false;
12 //Ensure last character is not a period
13 if (strEmail.Substring(strEmail.Length - 1, 1) == ".")
14  return false;
15 //Search for invalid chars
16 if (!System.Text.RegularExpressions.Regex.IsMatch(strEmail, "^[-A-Za-z0-9_@.']+$"))
17  return false;
18 //Search the @ char
19 Int32 i = strEmail.IndexOf("@");
20 //There must be at least three chars after the @
21 if (i <= 0 || i >= strEmail.Length - 3)
22  return false;
23 //Ensure there is only one @ char
24 if (strEmail.IndexOf("@", i + 1) >= 0)
25  return false;
26 //Ensure dot isn't next to @
27 if (strEmail.IndexOf(".@") >= 0 || strEmail.IndexOf("@.") >= 0)
28  return false;
29 //Ensure that the domain portion contains at least one dot
30 Int32 j = strEmail.LastIndexOf(".");
31 //It can't be before or immediately after the @ char
32 if (j < 0 || j <= i + 1)
33  return false;
34
35 //If we get here the, email address if good
36 return true;
37}

Photos on Flickr

More Photos »

Search Blog


Get Email Updates

Like what you read here at KeyLimeTie? Sign up for our email list!

Subscribe