IIS7 UrlRewrite Outbound links with Compression Enabled
Posted by shawson in IIS, URL Rewriting on August 22, 2011
I’ve recently started using the outbound link rewriting feature in the url rewrite module for IIS7, but initially ran into some problems.
In my web.config, my rewrite section (under system.webServer) looked something like this;
<rewrite>
<rules>
<rule name="InboundFriendlyAboutUs" stopProcessing="true">
<match url="^about-our-car-finance$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="About-Us.aspx" />
</rule>
</rules>
<outboundRules>
<rule name="OutboundFriendlyAboutUs" preCondition="IsHtml">
<match filterByTags="A, Form" pattern="^(.*)About-Us\.aspx$"/>
<action type="Rewrite" value="{R:1}about-our-car-finance"/>
</rule>
<preConditions>
<preCondition name="IsHtml">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html"/>
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
However when I tried to view the page I received a server error;
HTTP Error 500.52 – URL Rewrite Module Error.
Outbound rewrite rules cannot be applied when the content of the HTTP response is encoded (“gzip”).
This is because I also had the IIS7 dynamic and static compression enabled, as is sensible for any website. It turns out that, while dynamic compression is supported, static is not- and dynamic requires a little bit of fiddling to get going. I’ll boil it down to a few steps;
-
On the machine running the web site, from the command line run:
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\Rewrite /v LogRewrittenUrlEnabled /t REG_DWORD /d 0
You may need to follow this up with aniisreset -
Add the following to the top of your system.webServer section of your web.config file to disable the unsupported static compression while leaving dynamic unharmed;
<urlCompression doStaticCompression=”false” doDynamicCompression=”true” dynamicCompressionBeforeCache=”false” />
- The final step, is probably not needed- but! Open up your IIS management console- Click on the top level item, from the IIS segment open the “Modules” component. From within here on the right hand side bar, click “View ordered List…” and make sure RewriteModule appears in the list BELOW the DynamicCompressionModule. For me, this was already the case- my RewriteModule appeared at the very bottom, but this may not be the case for you.
If you’re after more details- my source was here; http://forums.iis.net/t/1165899.aspx
Best program for creating favicon’s– infact maybe the best program… ever!
Posted by shawson in Web Standards on August 19, 2011
Well maybe not ever.. but it’s pretty good for Icons. It’s called IcoFX – and it’s free!!
Refactoring a web project so you can share user controls across others
I recently built a brand new site, which launched last week and have now been tasked with adding an additional B2B component to it. The B2B site will have all the same styling as the B2C site, and will share a lot of functionality that I’ve already written into User Controls for the main web site. So I was faced with a problem- How can I share these controls across both projects? I don’t want to simply copy and paste, because then I have two controls to maintain, so I took to Google where I found this old article by Scott Guthrie.
I figured I would document the re-factoring exercise I went through.
So I started with my main web project which looked like this;
I shall break down the refactor into some simple steps;
- I created a new class library project which could be shared between the two web projects, in this instance I called mine Chinook.Web.Helpers
-
Create a “Controls” folder and drag all the controls from the original web project, into the new shared projects control folder (Make sure both the ASPX and the code behind parts came across!). Build the new shared project- you will probably find some build errors and will need to add references to some web specific .net dll’s- I needed
- System.Configuration
- System.Web
- System.Web.Extensions
- System.Web.Extensions.Design
- System.Web.Services
As well as these I also had to add references to my .Model and .Interfaces projects, but this will be different depending on how you’ve setup your project. At this stage I had a projects which built and looked like this;
-
I updated the namespace for each controls code behind and the first line of each ascx to reflect the namespace of the new project;
//namespace Chinook.Web.Controls namespace Chinook.Web.Helpers.Controls { public partial class QuickContact : System.Web.UI.UserControl..and the new inherits parameters in the ascx;
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="QuickContact.ascx.cs" Inherits="Chinook.Web.Helpers.Controls.QuickContact" %> - Next I added a reference in my web project to the new shared project, then deleted the controls from my controls folder, leaving an empty controls folder. All the references to the controls in your pages remain the same; for example
<%@ Master Language="C#" AutoEventWireup="True" CodeBehind="Site.master.cs" Inherits="Chinook.Web.SiteMaster" %> <%@ Register Src="Controls/RSSLister.ascx" TagName="RSSLister" TagPrefix="uc1" %> <!DOCTYPE html> <html lang="en"> <head runat="server"> ... <ul id="rss" class="orange-bullets"> <uc1:RSSLister ID="BlogRSSFeed" runat="server" /> </ul>
-
So the project is now happy- we just need to add the pre-build step which will copy the ascx files (but not the code behind) over to each projects control folder on pre-build. So in the original web project, right click the project and go to properties -> Build Events and set the pre-build event so that it copies;
copy $(SolutionDir)\Chinook.Web.Helpers\Controls\*.ascx $(ProjectDir)\Controls\
- Build and run your web project!
I also moved over a few other bits. I had an ashx file which handles file uploads- so I moved the code behind to the shared projects and just updated the ashx file to inherit from the same class, but in it’s new namespace. I also had a resx file which contained user friendly error messages which I moved to be central. My final helper looked like this;

Make sure that you don’t edit the ascx files that now exist within your web project, as there will be overwritten by the versions in the shared project everytime you re-build.
If you use the publish option (you probably do!), make sure you “show all files” on your web project after a build include the ascx files into your web project, so it gets copied up.
Wizard generated SSIS package dumps critical files in Temp folder- breaks after a log out!
Posted by shawson in SQL Server on August 5, 2011
I’ve recently spent a day of so of my life doing something which I did in minutes using DTS (And I’m sure on SSIS in the past??). I selected export data from a database in sql 2005 and chose my destination database and a bunch of tables. At the end I select save as SSIS package; everything runs fine.
I can exit the sql management studio, run the package again– all ok.
I then log out, log back in, run the package, and I’m swamped with errors about missing tmp files.
It turns out that the ssis wizard, dumps critical parts of the ssis package (table schema and the like) out into temp files (Only when you tick optimize for multiple tables- whcih I had to in order to be able to use transactions), which on our system gets wiped on logout- so when you come back, the package is crippled.
I found a solution on BigResource.com from user jaegd;
The Import/Export wizard created files are stored in the TMP environment variable by default.
To store the Import Export Data wizard files with a checked “Optimize for many tables” setting in a particular directory, create a batch file with the following contents (change the dir name to one you want) and run it.
set TMP=c:\place_for_files
dtswizard.exeThis approach just changes the TMP location temporarily to a place you’d prefer.
If you don’t want to create a batch file, just run the following from Start/Run…
cmd /c set TMP=c:\place_for_files && dtswizard.exe
This has fixed it! Such a relief- I set the env var tmp to c:\scripts\SSISFiles then generate the SSIS package, and save it to the file system in c:\scripts\ with no sensitive data embedded, then fire it off from the command line, supplying the connection strings.
dtexec.exe /FILE "C:\scripts\MySSISPackage.dtsx" /CONNECTION DestinationConnection;"\"Data Source=SiteDB\SQLEXPRESS;User ID=sync-user;Password=abc123;Initial Catalog=Chinook;Provider=SQLNCLI;Auto Translate=false;\"" /CONNECTION SourceConnection;"\"Data Source=CentralSQL;User ID=sync-user;Password=abc123;Initial Catalog=ProductDataStore;Provider=SQLNCLI;Auto Translate=false;\"" /MAXCONCURRENT " -1 " /CHECKPOINTING OFF /REPORTING V /CONSOLELOG NCOSGXMT >Log.txt
This way everything is kept nicely grouped together. Thought I would blog it for future me, and to prevent anyone else shaving 3 years off their life with stress.
New Adobe HTML5 Animation tool “Edge”- free tech preview
Posted by shawson in CSS, HTML5, Javascript on August 1, 2011
A real nail in the coffin for Flash, as it’s own parents (Adobe) release a free tech demo version of Edge- A new editor that lets you make flash style animations– without Flash! Instead the animations are scripted using standards html5, JavaScript and CSS3. Having been hand coding stuff like this over the past year (for 8week game and the like) I’m interested to see what kind of code this tool actually spits out! Check it out herel; http://t.co/I46QFYm
Overlapping arrow style menu, and CSS sprite sheets.
Bit of a weird post I guess… I was explaining to a friend how to implement a design they had in html/css and nocked together a reeeeally basic example, and figured I would post it incase it’s of any use to anyone else starting out in html/css. It’s a basic navigation bar where each button is shaped like an arrow, so the buttons all kind of overlap. There is an icon in each, which changes on mouse over, along with the background image of the button. Click the link below and check out the source- the sprite sheet can be viewed here http://codeblog.shawson.co.uk/storage/arrow-nav-bar-sprite-sheet/Sprite-sheet.png
The main example is here;
http://codeblog.shawson.co.uk/storage/arrow-nav-bar-sprite-sheet/
Adding minification and obfuscation of your Javascript and CSS to your ASP.net build process using Yahoo YUI Compressor
Posted by shawson in .net, C#.net, CSS, Javascript on July 22, 2011
I’ve just finished integrating Yahoo’s YUI Compressor into the MSBuild process for a new web probject I’m working on, and I thought I would document the process as there doesn;t seem to be a start to finish guide about anywhere.
To start with, let me just explain the structure I use for new Solutions;
C:\_Dev\MyNewWebsite\ C:\_Dev\MyNewWebsite\Artwork\ C:\_Dev\MyNewWebsite\BuildTools\ C:\_Dev\MyNewWebsite\Docs\ C:\_Dev\MyNewWebsite\Source\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.sln C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Controls\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Images\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Scripts\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Services\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Styles\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\MyNewWebsiteWeb.csproj C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Entities\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Entities\MyNewWebsiteEntities.csproj C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Interfaces\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Interfaces\MyNewWebsiteInterfaces.csproj C:\_Dev\MyNewWebsite\ThirdParty\
Firstly, download the dot net port of the YUI compressor from codeplex. I then extracted this into a new folder in the BuildTools folder. (there should be 2 dll files and one txt licence file.)
I then created a new MSBuild file called build-minify.xml, in the MyNewWebsite.Web project folder. That file looks like this;
<?xml version="1.0" encoding="utf-8"?>
<!-- http://yuicompressor.codeplex.com/wikipage?title=Sample%20MSBuild.xml%20File&amp;amp;amp;amp;ProjectName=yuicompressor -->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask
TaskName="CompressorTask"
AssemblyFile="..\..\BuildTools\Yahoo.Yui.Compressor-v1.5.0.0\Yahoo.Yui.Compressor.dll" />
<ItemGroup>
<CssFiles Include="$(SourceLocation)Styles\Fonts.css"/>
<CssFiles Include="$(SourceLocation)Styles\Site.css"/>
<CssIE Include="$(SourceLocation)Styles\IE.css"/>
<CssIE6 Include="$(SourceLocation)Styles\IE6.css"/>
<JsAll Include="$(SourceLocation)Scripts\jquery-1.6.1.min.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery-ui-1.8.14.custom.min.js" />
<JsAll Include="$(SourceLocation)Scripts\json2.js" />
<JsAll Include="$(SourceLocation)Scripts\jqModal-r14.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery.tipsy.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery.scrollTo-1.4.2.min.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery.localscroll-1.2.7.min.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-alert.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-validation.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-rollovers.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-custom-accordion.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-vehicle-lookup.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-sandbox.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-finance-calculator.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-apply-now.js" />
</ItemGroup>
<Target Name="Minimize">
<CompressorTask
CssFiles="@(CssFiles)"
DeleteCssFiles="false"
CssOutputFile="Styles/Site.rel.css"
CssCompressionType="YuiStockCompression"
DisableOptimizations="Nope"
EncodingType="Default"
LineBreakPosition="-1"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
<CompressorTask
CssFiles="@(CssIE)"
DeleteCssFiles="false"
CssOutputFile="Styles/IE.rel.css"
CssCompressionType="YuiStockCompression"
DisableOptimizations="Nope"
EncodingType="Default"
LineBreakPosition="-1"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
<CompressorTask
CssFiles="@(CssIE6)"
DeleteCssFiles="false"
CssOutputFile="Styles/IE6.rel.css"
CssCompressionType="YuiStockCompression"
DisableOptimizations="Nope"
EncodingType="Default"
LineBreakPosition="-1"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
<CompressorTask
JavaScriptFiles="@(JsAll)"
ObfuscateJavaScript="true"
PreserveAllSemicolons="true"
DisableOptimizations="false"
EncodingType="Default"
DeleteJavaScriptFiles="false"
LineBreakPosition="-1"
JavaScriptOutputFile="Scripts/chinook.rel.js"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
</Target>
</Project>
You can create whatever ItemGroups you’d like- then just create a compressor task for each. For a rundown of the settings, check out the link in the comment at the top of the XML there. In the above file I had decided to compress all of my Javascript into a single file called chinook.rel.js, and my fonts and site css file rolled into one file, keeping the ie6 css separate, but still minifying it down.
The next step is to add it to the normal build. I opened the solution in Visual Studio, right clicked my web project and selected properties. Go to “Build Events” and add the following post-build event;
$(MSBuildBinPath)\msbuild.exe $(ProjectDir)build-minify.xml /target:Minimize
Now you can test it out by building your project. The new minified files are dumped out, in my case to the Scripts folder. Now that the files are there, I need a way of telling my release version of the website to use these instead of the raw, human-readable versions; but I still want to continue using the human-readable versions for development.
To achieve this I use pre-processor directives. These are most commonly seen in the c# code behind files, but can also be used in the aspx files. I added the following lines at the bottom of my master page;
<% #if (!DEBUG) %>
<script src="Scripts/chinook.rel.js" type="text/javascript"></script>
<% #else %>
<script src="Scripts/jquery-1.6.1.min.js" type="text/javascript"></script>
<script src="Scripts/jqModal-r14.js" type="text/javascript"></script>
<script src="Scripts/chinook-alert.js" type="text/javascript"></script>
<script src="Scripts/jquery-ui-1.8.14.custom.min.js" type="text/javascript"></script>
<script src="Scripts/chinook-vehicle-lookup.js" type="text/javascript"></script>
<script src="Scripts/chinook-sandbox.js" type="text/javascript"></script>
<script src="Scripts/chinook-finance-calculator.js" type="text/javascript"></script>
<script src="Scripts/jquery.scrollTo-1.4.2.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.localscroll-1.2.7.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.tipsy.js" type="text/javascript"></script>
<script src="Scripts/json2.js" type="text/javascript"></script>
<script src="Scripts/chinook-validation.js" type="text/javascript"></script>
<script src="Scripts/chinook-apply-now.js" type="text/javascript"></script>
<script src="Scripts/chinook-rollovers.js" type="text/javascript"></script>
<script type="text/javascript" src="Scripts/chinook-custom-accordion.js"></script>
<% #endif %>
So if the project is NOT running in debug mode, I import my full chinook.rel.js include which has everything already included, otherwise I manually include all the human readable, separate files.
And that’s pretty much it. Make sure you thoroughly retest your site with your combined java script file, as sometimes minification can cause issues with some code.
Handy article on running IE 6, 7 & 8 alongside each other on Win7 using XP mode
Posted by shawson in Cross Browser Testing, Web Standards on July 19, 2011
Entity Framework 4.1 Code First (With One to Many relationship) Code Example
Posted by shawson in .net, C#.net, Entity Framework, Linq on July 10, 2011
A quick piece of code demo’ing a very common/ simple usage scenario- basic one to many with some demo data being seeded into the database; I thought this might be needed as I’ve waded through a LOT of exmaples for various beta versions and different releases of EF, but had little luck actually finding something relevant. The best site I came across was tucked away on the ADO.net team’s blog- Using DbContext in EF 4.1. First– the entities and the database context
public class Category
{
[Key]
public Guid ID { get; set; }
public string Title { get; set; }
public virtual ICollection<Product> Products { get; set; }
//virtual makes this lazily loaded
public Category()
{
this.ID = Guid.NewGuid();
}
}
public class Product
{
[Key]
public Guid ID { get; set; }
public string Title { get; set; }
public string Details { get; set; }
public double Price { get; set; }
public string ImageFileName { get; set; }
public DateTime DateAdded { get; set; }
public virtual Category Category { get; set; }
//virtual makes this lazily loaded
public Product()
{
this.ID = Guid.NewGuid();
}
}
public class MyDBContext: DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
Note the use of ICollection on Products in Category, and the use of DbSet in the context. I used a DbSet in lieu of ICollection on the Products entity and found it went mental if I had a Product with no category (something which I wanted to be valid) – swapping it to ICollection fixed this issue (I don’t know enough of the inner workings to explain why)
BAMM! Next for the seeding- add a class like so;
public class MyDBInitializer : DropCreateDatabaseAlways<MyDBContext>
{
protected override void Seed(Entities.ComicolleDB context)
{
Category marvel = new Category()
{
Title = "Category 1"
};
Category dc = new Category()
{
Title = "Category 2"
};
context.Categories.Add(marvel);
context.Categories.Add(dc);
context.Products.Add(new Product()
{
Title = "Test1",
ImageFileName = "image-1.gif",
Details = "This is a test",
Price = 4.99,
DateAdded = DateTime.Now,
Category = marvel
});
context.Products.Add(new Product()
{
Title = "Test2",
ImageFileName = "image-1.gif",
Details = "This is a test",
Price = 4.99,
DateAdded = DateTime.Now,
Category = dc
});
context.Products.Add(new Product() // no category
{
Title = "Test3",
ImageFileName = "image-1.gif",
Details = "This is a test",
Price = 4.99,
DateAdded = DateTime.Now
});
context.SaveChanges();
}
}
Then add the following line to the end of your Application_Start() method in global.asax;
Database.SetInitializer<MyDBContext>(new MyDBInitializer());
Voila- you can then go ahead and use your model in whatever applications you see fit- here are some example;
MyDBContext db = new MyDBContext();
// get a category, and make sure the products are loaded
Category the_category = db.Categories.Include("Products")
.Where(x => x.Title == "Category 1").SingleOrDefault();
// get all the products for that category
List<Product> some_products = the_category.Products;
// get all the categories (without loading the products)
List<Category> some_categories = db.Categories.ToList();
Netgear ReadyNAS Duo command line shut down utility
Posted by shawson in .net, C#.net, Networking on July 4, 2011
So I finished the backup app and compiled it for anyone who wants it- it’s used from the command prompt like so;
ShutdownNASBox -h <hostname> -u <username> -p <password>
eg.
ShutdownNASBox -h backup -u admin -p abc123
If you run the tool with administrator privileges, it will log to the Windows Event Log on the System tab.
You can download it here (note you will need dot net framework 4 installed)

