Galin Iliev's blog

Software Architecture & Development

Breaking changes in IIS7 (integrated pipeline) when hosting ASP.NET 2.0 sites

Mike Volodarsky posted a nice list of breaking changes when you run ASP.NET 2.0 web sites on IIS7 Integrated mode.

Here is the list (for workarounds take a look at Mike's blog post).

Migration errors
  1. ASP.NET applications require migration when specifying configuration in <httpModules> or <httpHandlers>.
  2. ASP.NET applications produce a warning when the application enables request impersonation by specifying <identity impersonate=”true”> in configuration.
  3. You receive a configuration error when your application configuration includes an encrypted <identity> section.
Authentication, Authorization, and Impersonation

  1. Applications cannot simultaneously use FormsAuthentication and WindowsAuthentication.
  2. Windows Authentication is performed in the kernel by default.  This may cause HTTP clients that send credentials on the initial request to fail.
  3. Passport authentication is not supported.
  4. HttpRequest.LogonUserIdentity throws an InvalidOperationException when accessed in a module before PostAuthenticateRequest.
  5. Client impersonation is not applied in a module in the BeginRequest and AuthenticateRequest stages.
  6. Defining an DefaultAuthentication_OnAuthenticate method in global.asax throws PlatformNotSupportedException.
  7. Applications that implement WindowsAuthentication_OnAuthenticate in global.asax will not be notified when the request is anonymous.
Request limits and URL processing
  1. Request URLs containing unencoded “+” characters in the path (not querystring) is rejected by default.
  2. Requests with querystrings larger then 2048 bytes will be rejected by default.
Changes in response header processing
  1. IIS always rejects new lines in response headers (even if ASP.NET enableHeaderChecking is set to false)When the response headers are cleared with HttpResponse.ClearHeaders, default ASP.NET headers are not generated.  This may result in the lack of Cache-Control: private header that prevents the caching of the response on the client.
  2. When the response is empty, the Content-Type header is not suppressed.
  3. When the response headers are cleared with HttpResponse.ClearHeaders, default ASP.NET headers are not generated.  This may result in the lack of Cache-Control: private header that prevents the caching of the response on the client.
Changes in application and module event processing
  1. It is not possible to access the request through the HttpContext.Current property in Application_Start in global.asax.
  2. The order in which module event handlers execute may be different then in Classic mode.
  3. ASP.NET modules in early request processing stages will see requests that previously may have been rejected by IIS prior to entering ASP.NET.  This includes modules running in BeginRequest seeing anonymous requests for resources that require authentication.
Other application changes
  1. DefaultHttpHandler is not supported.  Applications relying on sub-classes of DefaultHttpHandler will not be able to serve requests.
    It is possible to write to the response after an exception has occurred.
  2. It is not possible to use the ClearError API to prevent an exception from being written to the response if the exception has occurred in a prior pipeline stage.
  3. HttpResponse.AppendToLog does not automatically prepend the querystring to the URL.
Other changes
  1. ASP.NET threading settings are not used to control the request concurrency in Integrated mode.
  2. ASP.NET application queues are not used in Integrated mode.  Therefore, the “ASP.NET Applications\Requests in Application Queue” performance counter will always have a value of 0
  3. IIS 7.0 always restarts ASP.NET applications when changes are made to the application’s root web.config file.  Because of this, waitChangeNotification and maxWaitChangeNotification attributes have no effect.

Employees will never perform like founders!

That's the true! No matter how you motivate and stimulate them, they will never will perform like the founders in long run. And this cannot and shouldn't be expected from them. They care about what's their job like today! They won't sacrifice for long run.

Founders are another story. They work tireless days, nights, during weekends putting on risk family relationships, friendships and even their health. But the bet is a way different. Success could bring them a fortune.

On the other hand success will bring a bigger salary, bonus, maybe shares to employees. No matter how big these are they cannot compete with the benefits of the founders. That's why there will always be difference between founders and employees.

In software business is normal to have 2-3 guys who makes a small company and create first version of the product. This version is created in no time - everyone in the team knows all the details and work on them no matter of the clock. And when this version is a blockbuster and it is time to hire some hands to help on next one the expectations are so high. Performance will never be the same.

Note: I am not saying that it is bad being an employee or a founder. Each situation has its own pros and cons :).

(These thoughts are inspired by Joel Spolsky's article "How Hard Could It Be?: Lessons I Learned in the Army")

Run scheduled tasks in managed code

Easy thing, isn't it? Just have to create a database that will have all tasks with relevant information about them and then create a service which will pull them and execute the tasks when needed. Not so hard! As making a wheel :) Just bend a thin wood!

Alternatively you might consider using Windows Task Scheduler.

Bart De Smet wrote an article "Calling the Task Scheduler in Windows Vista (and Windows Server 2008) from managed code"

Hope this helps :)

IIS7: How to set cache control for static content?

Caching is popular technique for reducing network traffic and server recourses when it comes to web content. But how we can cache static content like .jpg, gif, .js files?! 

Seems easy: just start IIS Manager... and ... Wait! there is no icon for it there! Hmm

it's not so easy though... but possible:

just follow these steps:

1. Allow overriding static content setting:

open %systemroot%\System32\inetsrv\config\applicationHost.config
search for <section name="staticContent" overrideModeDefault="Deny" />

change it to <section name="staticContent" overrideModeDefault="Allow" />

 

2. set cache settings using following commands (from IIS.NET forums)

set max-age to 1hr for all static files under /images on default-web-site, run the following

 

\Windows\system32\inetsrv\appcmd.exe set config "Default Web Site/images" -section:system.webServer/staticContent -clientCache.cacheControlMode:UseMaxAge

 

\Windows\system32\inetsrv\appcmd.exe set config "Default Web Site/images" -section:system.webServer/staticContent -clientCache.cacheControlMaxAge:"01:00:00"

 

If you give it a shot now you will see that the content is cached! Not believe?! Try to request image from the browser, overwrite the image with image with same name and different content and request image from the browser again...

But the bad news is that caching is on the server - so you haven't reduced network traffic as web server is still hit.

 

3. Cache it on client

open %systemroot%\System32\inetsrv\config\applicationHost.config

and change the lines like this

 

<location path="MyWebsite"> 
    <system.webServer> 
        <caching> 
            <profiles> 
                <add extension=".html" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".htm" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".gif" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".js" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".css" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".jpg" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".jpeg" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".zip" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
                <add extension=".rar" policy="CacheUntilChange" kernelCachePolicy="DontCache" location="Client" /> 
            </profiles> 
        </caching> 
    </system.webServer> 
</location>

 

So it is done :)

Thanks to Aaron Murray

Stress testing with WCAT

Recently I had a case in which I had to prove that load on IIS is too heavy for hosted web applications. While looking for appropriate tool I came across Microsoft Web Capacity Analysis Tool (WCAT) - not very popular tool but very powerful one.

As it wasn't easy to setup and run it I've decided to write an article which summarizes the information you need to run load test with WCAT.

Most of the information is in WCAT 6.3 documentation but I found that it isn't natural easy to run it.

Read Stress testing with Microsoft Web Capacity Analysis Tool (WCAT) article and I hope you'll find it helpful.

Any feedback is appreciated.

Cool commands for Visual Studio

Do you know the great Visual Studio 2003/2005/2008 add-in called CoolCommands and it written by Gaston Milano? It has some very nice features and it is very easy to get used to it. There is a little hassle to run it on VS 2008 but keep reading - on the bottom of this post are the required steps.

Here is what makes me use CoolCommands:

Locate in Solution Explorer

Expands solution explorer's tree in order to select opened file - very helpful with huge projects while 'Go to definition' command is used to jump from one project to another.

image

Demo Font

Quickly toggles between an 18-point font size and your preferred (Tools | Options | Environment | Fonts & Colors) font size. This is very handy shortcut for while you're giving a presentation.

image

Add As String Resource

Context menu item displayed in response to a right-click in a text editor window - Pops up a dialog to allow you to easily specify a key and value (defaults to the selected text), and a dropdown list of resource files to which you can add the new string resource.

 

These ones impressed me much but read about all the features on Brian Schoroer blog post.

Here is how to install:

Luckily there is version 4 and it supports Visual Studio 2008 but with little changes.

  1. Download v4.
  2. Extract it to a folder you won't delete later
  3. modify setup.bat to include this line
    regpkg CoolCommands.dll /root:Software\Microsoft\VisualStudio\9.0 /codebase
  4. Run setup bat and it is done!

How (not) to bloat SQL Server execution plan cache?!

Short answer: don't use SqlParameterCollection.AddWithValue() method!

Why?! Because if you have query like this:

   1: string lastName = "Galcho";
   2:  
   3: SqlCommand selectCommand = new SqlCommand(
   4:         "SELECT ContactID, FirstName, LastName
   5:         FROM AdventureWorks.Person.Contact
   6:         WHERE LastName = @LastName",
   7:         connection);
   8:  
   9:  
  10: selectCommand.Parameters.AddWithValue("@LastName", lastName);

the execution plan cache entry is like this

(@LastName nvarchar(6))SELECT ContactID, FirstName, LastName FROM AdventureWorks.Person.Contact WHERE LastName = @LastName

So if you execute the code with different value in lastName variable you'll get different first part of the cached executed plan.

Using selectCommand.Parameters.Add("@LastName", SqlDbType.NVarChar, 50).Value = lastName; instead is a way better.

Read full story here

So, what's new in .NET 2.0?

That's right! There is new stuff in .NET 2.0 SP1 libraries and you should know about changes in red bits because there will be MethodMissingException exceptions if you deploy solution developed with VS 2008 with .NET 2.0 as target framework and deploy it on machine with .NET 2.0 (without SP1).

Scott Hanselman created a nice compilation with changes.

Note: this do not affect existing solutions at all because of .NET framework compatibility policy unless you've taken an advantage of fixed bug. In this case you should test affected components (UPDATED in order to include valueable comments from Daniel Moth)

blog posts on the subject:

Microsoft Office file formats' specifications

You've probably heard about Office Open XML File formats. It is zipped folder which includes content in XML format as well as the code and included files. This means you can take a look inside them by simply changing the extension:

docxzipfiles

This is not new and there are plenty of article about this on the web.

The news here is that Microsoft published Microsoft Office Binary (.doc, .xls, .ppt) file formats specifications. It could be very interesting... But it could be boring too :) because according Joel Spolsky:

A normal programmer would conclude that Office’s binary file formats:

  • are deliberately obfuscated
  • are the product of a demented Borg mind
  • were created by insanely bad programmers
  • and are impossible to read or create correctly.

There is a good article from Joel Spolsky who is former PM @ Microsoft Excel team that analyze the specification.

Read it to find out how complex data are handled in limited CPU power and memory back in 80386 at 20 MHz