Category Archives: C#

Helicion Tech ISAPI 3 Rewrite Problem with ASP.NET 4.0, IIS6 & Extensionless URLs

For years we have used Helicon Tech’s ISAPI Rewrite plugin for IIS to generate pretty URLs for our ASP.NET sites.  A few months back I was in the process of migrating our ASP.NET web applications to the 4.0 Framework and I ran into an issue with ISAPI Rewrite and our site’s URLs.  Basically, it turned out that ISAPI Rewrite wasn’t even getting the chance to process our URL rewrites as it should.

The bottom line here is that with the 4.0 Framework and IIS 6.0, Extensionless URLs are turned on by default.  Since our rewrites were dependent on the ASPX extension to map our pretty URLs to actual pages, I had to turn this feature off.  To fix this, I had to go into the registry and find this key value:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\

Then I had to add/edit this DWORD value:

EnableExtensionlessUrls = 0

I restarted IIS and ISAPI Rewrite worked like a charm.  I didn’t have this issue on my development box which runs 64-bit Windows 7 Professional and IIS 7.5.  I only had this issue on our testing and production environments which run Windows 2003 and IIS 6.0.

SqlCacheDependency and Query Notifications

There’s a lot of scattered information out there on how to configure ASP.NET applications to leverage Microsoft SQL Server’s Query Notification and Service Broker services for caching in ASP.NET applications. The two best step by step tutorials I’ve found online are:

http://www.simple-talk.com/sql/t-sql-programming/using-and-monitoring-sql-2005-query-notification/

http://dimarzionist.wordpress.com/2009/04/01/how-to-make-sql-server-notifications-work/

Both of those articles should get you started for sure. I ran into issues keeping our application from crashing after a period of time though while leveraging Query Notifications for caching in a few of my sites. The biggest issue I found was that I would see the following exception in our logs:

When using SqlDependency without providing an options value, SqlDependency.Start() 
must be called prior to execution of a command added to the SqlDependency instance.

Never did quite get a handle on what was going on here. I did figure out though that I could always find this in my Application log around the time that exception was thrown:

The query notification dialog on conversation handle '{A1FB449B-DEB3-E011-B6D2-002590198D55}.' closed due to the following error: '-8470Remote service has been dropped.'.

So, does this mean that I called SqlDependency.Stop() and now queued notifications aren’t going to be delivered. Are these critical errors that keep the application from coming back? I’ve read that a lot of the Query Notification messages you see in the log aren’t critical errors and can be ignored. I can’t ignore the timing of this error and the exception being thrown above though.

Anyway, I finally decided to pull this stuff out of our application until I get a better handle on what’s going on. The last straw was that I was trying to sync some database changes during a maintenance period and I couldn’t get them to sync because of a bunch of these SQL Query Notification issues. As I write this, I can’t even get my database back online as I’m waiting for ALTER DATABASE SET SINGLE_USER to complete (approaching 3 hours!!!). As I keep waiting, my Application log keeps filling up with the following Query Notification messages:

Query notification delivery could not send message on dialog ‘{FE161F6A-D6B3-E011-B6D2-002590198D55}.’. Delivery failed for notification ‘85addbaa-ce66-431d-870f-d91580a7480a;d527d584-9fd4-4b13-85bc-87cb6c2e166f‘ because of the following error in service broker: ‘The conversation handle “FE161F6A-D6B3-E011-B6D2-002590198D55” is not found.’.
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

I had a response to a post I made on the ASP.NET Forum and it was suggested that with all the cached items in the system, that SQL Server really could not catch up. This is a problem because not only does it slow the entire system down, but when you have to cycle the SQL Server service itself, it takes forever for the system to come back up because all of the notifications get requeued or something.

Determine if Amazon S3 Object Exists with ASP.NET SDK

After my earlier posts on invalidating Amazon CloudFront objects, I thought it would be important to see if an Amazon S3 object existed before trying to invalidate it. With the 1,000 request limit on invalidation requests before Amazon charges you for them, this seemed to be a prudent thing to do. So, I turned to the Amazon Web Services ASP.NET SDK to help me out with it. This is what I came up with:

public bool S3ObjectExists(string bucket, string key)
{
    using (AmazonS3Client client = new AmazonS3Client(this._awsAccessKey, this._awsSecretKey))
    {
        GetObjectRequest request = new GetObjectRequest();
	request.BucketName = bucket;
	request.Key = key;

	try
	{
		S3Response response = client.GetObject(request);
		if (response.ResponseStream != null)
		{
			return true;
		}
	}
	catch (AmazonS3Exception)
	{
		return false;
	}
	catch (WebException)
	{
		return false;
	}
	catch (Exception)
	{
		return false;
        }
    }
    return false;
}

I decided that if I found a valid ResponseStream on the S3Response, then I had a valid object. All I’m checking on is the object key itself, i.e. an image path in S3. Another note here is I’m checking for three different exceptions but returning false for all 3. The reason I have this coded this way for now is I wanted to see what different exceptions GetObject might throw depending on what was wrong with the request. This was done purely for testing purposes and will probably be changed in the future. For instance, I discovered that AmazonS3Exception is thrown when the object isn’t there. WebException is thrown when the object is there, but the request cannot be completed. I’m still in the testing phase with this, but I hope this helps some other Amazon Web Service developers out there.

Adding an Image to a PDF Document Using C# and PdfSharp

A while back I wrote about generating PDF documents using PdfSharp. It worked really well for us to generate invoices and purchase orders on the fly to ship orders and receive product. One must on our invoices was showing our corporate logo on our invoices that went out to our customers. We also wanted to do the same on the documents we generated for our purchase orders so that our vendors could easily identify our company when processing the order. This turned out to be a snap using PdfSharp.

void AddLogo(XGraphics gfx, PdfPage page, string imagePath, int xPosition, int yPosition)
{
    if (!File.Exists(imagePath))
    {
	throw new FileNotFoundException(String.Format("Could not find image {0}.", imagePath));
    }

    XImage xImage = XImage.FromFile(imagePath);
    gfx.DrawImage(xImage, xPosition, yPosition, xImage.PixelWidth, xImage.PixelWidth);
}


try
{
    PdfDocument doc = new PdfDocument();
    PdfPage page = doc.AddPage();
    
    XGraphics gfx = XGraphics.FromPdfPage(page);
    
    AddLogo(gfx, invoice, "pathtoimage", 0, 0);
}
catch (Exception)
{
    // Handle exception
}

The arguments to DrawImage on the XGraphics object specify an XImage object, the starting position of the image (0, 0 in this case), and the dimensions of the image. You can get the dimensions easily from the PixelWidth and PixelHeight properties (the Width and Height properties can be used, but are deprecated) of the XImage object.

Then call the AddLogo() method above to draw your image in the document. Positioning and image dimensions are important to get correct otherwise the image won’t draw properly in your document. Keep track of where you place your logo when drawing text or additional images on your document as well. If you don’t keep track of positioning from element to element, you’ll actually draw over previous elements.

C# Inferring SqlDbType via Reflection

Today, I was looking for a way to take a string representation of a SqlDbType, i.e. System.Data.SqlDbType.VarChar and actually return the enumeration value (System.Data.SqlDbType is an enumeration of valid SQL data types like VarChar, Char, Int, etc.). Of course I could have done something like:

public static SqlDbType GetSqlDbType(string sqlDbType)
{
    switch (sqlDbType)
    {
	case "varchar":
		return SqlDbType.VarChar;
	case "char":
		return SqlDbType.Char;
	case "int":
		return SqlDbType.Int;	
	case "bigint":
		return SqlDbType.BigInt;
	default:
		throw new Exception(String.Format("{0} is either an unknown or unsupported SqlDbType.", sqlDbType));
    }
}

The drawback to this solution is that I would need a giant switch statement for all of the possible SqlDbType possibilities. Plus, what if for some magical reason, a new one is added? So I turned to Google to help me find a more elegant example, and I found what I was looking for:

SqlDbType sdt = (SqlDbType)Enum.Parse(typeof(SqlDbType), "VarChar", true);

This allows you to find the SqlDbType value you are looking for by using reflection on the SqlDbType enumeration. Nice! Of course, I wanted a more complete solution for my needs, so I came up with something like this (based on the first example):

public static SqlDbType GetSqlDbType(string sqlDbType)
{
    if (!String.IsNullOrEmpty(sqlDbType))
    {
	try
	{
	    string hintText = sqlDbType.Substring(sqlDbType.LastIndexOf(".") + 1);

	    SqlDbType sdt = (SqlDbType)Enum.Parse(typeof(SqlDbType), hintText, true);
	    return sdt;
	}
	catch (ArgumentException)
	{
	    throw new Exception(String.Format("{0} is an unknown SqlDbType.", sqlDbType));
	}
	catch (Exception e)
	{
	    throw e;
	}
    }

    throw new Exception("Provided value for SqlDbType was null or empty.");
}

This lets us do a couple of important things. First, it allows for support of the complete namespace for a SqlDbType, i.e. System.Data.SqlDbType.VarChar AND just VarChar. Second, it lets us catch important errors like an unknown SqlDbType value that is passed in to GetSqlDbType.

That’s it! Enjoy! If anyone has any questions or comments, you know what to do…

Invalidating Content on Amazon CloudFront with ASP.NET SDK

I’m working on integrating some of Amazon’s Web Services into out eCommerce platform. I’ve been working on performance enhancements on and off for the last year and content delivery is the last big step for us. Getting started on S3 and CloudFront was pretty easy, but I ran into some issues when updating content in our S3 buckets. Luckily, Amazon added the ability to do this at the end of August. Since we use ASP.NET, I’ve started to work with their .NET SDK. Turns out, its pretty easy to invalidate some content.

public bool InvalidateContent(string distributionId, List<string> files)
{
    AmazonCloudFrontClient client = new AmazonCloudFrontClient(Settings.AWSAccessKey, Settings.AWSSecretKey);

    PostInvalidationRequest request = new PostInvalidationRequest();
    InvalidationBatch batch = new InvalidationBatch();

    batch.Paths = files;
    batch.CallerReference = GetHttpDate();

    request.InvalidationBatch = batch;
    request.DistributionId = distributionId;

    PostInvalidationResponse response = client.PostInvalidation(request);
    if (!String.IsNullOrEmpty(response.RequestId))
    {
	bool bInProgress = true;
	while (bInProgress)
	{
	    GetInvalidationRequest getReq = new GetInvalidationRequest();
	    getReq.DistributionId = distributionId;
	    getReq.InvalidationId = response.Id;

	    GetInvalidationResponse getRes = client.GetInvalidation(getReq);
	    bInProgress = getRes.Status.Equals("InProgress");

	    if (bInProgress)
	    {
		Thread.Sleep(Settings.AmazonWaitTime);
	    }
	}
    }
    else
    {
	return false;
    }

    return true;
}

InvalidateContent expects a CloudFront Distribution ID and a list of S3 files to invalidate. References to the static Settings class is just a class that reads in configuration settings from a configuration file, be it App.config or any configuration file you wish to set up. Basic values to store are your AWS Access Key, AWS Settings Key, and a wait time value before requesting information from Amazon again. There is also a method GetHttpDate(), which just returns:

System.DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss ", System.Globalization.CultureInfo.InvariantCulture) + "GMT";

InvalidateContent() will make a PostInvalidationRequest (which is part of the ASP.NET AWS SDK) through an AmazonCloudFrontClient object. If this request is successfully posted, Amazon will return you a RequestId value that you can use to poll for the completion of your request. Keep in mind that you can only invalidate 1,000 S3 objects a month. After that Amazon will start to charge you $0.005 per object invalidated. This is per file, not per invalidation request. Hopefully you found this helpful!

ASP.NET SQLCacheDependency with SQL Query Notifications

I’m going to make this quick and dirty. I’ve set up my ASP.NET web applications to leverage SQLCacheDependency with SQL Server 2005 Query Notifications. The setup process takes a some time and debugging can be tricky. But the payoff can be enormous. The bottom line is that the performance increase on page load times is well worth the effort, especially for data that doesn’t change all that often. I found it really useful for caching product data on my eCommerce sites, especially as the number of products in the system grew to over 5,000. However, I always seem to miss a step when when configuring my SQL Server 2005 databases; so this post is for my own reference, but if it helps someone else out there, even better.

The original article I used as a basis for configuring my applications is at the url below:

http://www.simple-talk.com/sql/t-sql-programming/using-and-monitoring-sql-2005-query-notification/

Follow the steps there and you’re good to go. Especially use the SQL Profiler debug steps at the bottom of the article if you get tripped up. One thing that I always had to do with my databases to get everything to work properly was execute the following query:

use <dbname>
EXEC dbo.sp_changedbowner @loginame = N'<dbuser>', @map = false

Make sure you use this caching technique responsible though. The Query Notifications can use up processing power so only cache data that you know will give your application a performance bump. Also beware of memory usage as you cache more and more data. You could end up caching so much data your application needs to restart often and that could cause slow page load times.

Easily Cause StackOverflow Exception in ASP.NET Web Application

This is a short one, but since I can’t believe I’ve never managed to do this before, I thought I’d post a little tidbit on it. I threw a StackOverflow in one of my ASP.NET C# web applications today. Watching the request keep going for about 5 minutes, I checked the Event Log on the server. There it was, StackOverflow exception. Say, what?

How did I manage it? Recursively add a control to its own control collection. The .NET framework just freaks and the application pool just gets restarted after each exception kills the app. Glad it didn’t take long to figure it out!

Properties In a Active Directory Computer Object

I’m working on a project and I was curious about what properties Active Directory would return when search for computers with the DirectorySearcher class in C#. Basically, you can search an entire domain for known computers using something like:

string domainName = "mydomain";
DirectoryEntry de = new DirectoryEntry();
de.Path = String.Format("LDAP://{0}", domainName);
de.Username = "username";
de.Password = "password";

try
{
     DirectorySearcher ds = new DirectorySearcher();
     ds.Filter = "(&ObjectCategory=computer)";
     SearchResultCollection results = ds.FindAll();

     foreach (SearchResult sr in results)
     {
             ResultPropertyCollection myResultPropColl;
             myResultPropColl = sr.Properties;
             foreach (string myKey in myResultPropColl.PropertyNames)
             {
                 string propString = String.Empty;
                 string tab = "    ";                                
                 Console.WriteLine("{0} = ", myKey);
                 foreach (Object myCollection in myResultPropColl[myKey])
                 {
                     Console.WriteLine("{0}{1}", tab, myCollection);
                 }
         }
     }
}
catch (Exception)
{
}

This code is basically borrowed from this MSDN article, but what I was originally after was what properties could I actually get at? I wasn’t all that interested in the code. Well, just running that code yielded me the following list of properties that you can access via a computer object from Active Directory:

operatingsystem
countrycode
cn
lastlogoff
dscorepropagationdata
usncreated
objectguid
iscriticalsystemobject
serviceprincipalname
whenchanged
localpolicyflags
accountexpires
primarygroupid
badpwdcount
objectclass
instancetype
objectcategory
whencreated
lastlogon
useraccountcontrol
samaccountname
operatingsystemversion
samaccounttype
adspath
serverreferencebl
dnshostname
pwdlastset
ridsetreferences
logoncount
codepage
name
usnchanged
badpasswordtime
objectsid
distinguishedname

For my purposes, I wanted to find out operating system information, so the operatingsystem and operatingsystemversion properties woulded nicely for me. But, there you go, all of the properties you can access from a computer object in Active Directory. I hope this is useful to someone else out there other than myself.

Create PDF Documents in C# on the Fly with PdfSharp

Recently I was doing a freelance project and had to find a way to create PDF documents on the fly in a C# application. I figured the best approach would be to create PDF files that could be printed, then archived for retrieval at a later date. There are definitely libraries out there that you can pay for to help with this, but I really wanted something that was OpenSource. Luckily, I found PdfSharp!

You can pretty much draw anything for your PDF document using PdfSharp, shapes, text, images, etc. and you have full control over the fonts and the font weight. This gives you a lot of flexibility in creating your custom PDF documents. I highly recommend checking it out if you’re looking for a cheap (free is the best!) solution for your document creation.