ReBuildAll Blog
Thoughts (mostly) on .NET development

Moving ASP.NET Identity model into another assembly   (ASP.NET)   
Visual Studio 2013 and MVC 5 has arrived (as well as the "One ASP.NET"), with ASP.NET Identity in tow. The new identity feature allows user profile information to be part of the ASP.NET Identity model. In essence, the identity data structure can be merged with whatever data your application has, creating a seamless integration of identity data and application data.

The result? You do not need to have two data models / entity models for your application (and as such, two Entity Framework DbContext's).

Microsoft also provides a description of how this can be achieved, using Entity Framework migrations.

But what if you want your data model to live in another assembly, not the default web application? Reasons for such a thing might be a shared data access layer between different applications. You could have a Web application and another service that does background processing, both of which need access to your data.

The default ASP.NET MVC 5 project will have an IdentityModel.cs file in the Models folder. This contains the expandable identity model. But it is included in your Web application.

This is a description of how you move the identity model to another DLL.

Add a class library
The first step in moving your data access logic to a central assembly is adding a new class library project to your solution. This new class library will contain the data access layer, and you will reference it from other projects that need data access.

Go into NuGet package management, and add the Microsoft ASP.NET Identity EntityFramework package to the project. This will also pull in some dependencies.

Now you are all setup to actually move the identity model here.

Move over the identity model
Next, take your Models/IdentityModel.cs file from the Web application and move it into the new class library. (Move, and do not copy it. It should not be in the Web application after this step).

Change the namespace in the file to match that of your intended data access layer.

Optionally, you might want to create a separate file for the data context class. This would be a good time to do that.

Add references and usings
Last step, go back to your Web project and add a reference for the data access library.

Open AccountController to add a new using statement for your new data access namespace.

Start working on the data access layer
And now you are done. You can now add your entity classes and add IDbSet properties to the data context class. Build your data access layer. You will have only one data context class, that has both your application data and your identity data together.

WSDLMerge v1.2   (ASP.NET)   
WSDLMerge updated with small bugfix. Available from the project's google code page as usual. Both source and binary.

UI Kompositio   (ASP.NET)   
This article is only available in Finnish. It relates to my talk at Tech Days Finland 2012.

8.3.2012 pidetyssä Tech Days 2012 Finland tapahtumassa olin puhumassa UI Kompositio aiheesta, miten rakennetaan käyttöliittymää käyttäen Javascriptiä pienistä paloista. Tästä löydät esityksen PowerPoint sekä PDF muodossa, ja demo sovelluksen.

Kun lataat demo sovelluksen, muista lukea asennus.txt tiedoston mikä kertoo miten tietokannat ja ympäristö rakennetaan.

UI Komposition esitys (.pdf)

UI Komposition esitys (.pptx)

UI Komposition demo (.zip)

LINQ CreateDatabase cannot resolve DataDirectory   (ASP.NET)   
You might be familiar with SQL Server Express User Instances. These are per user copies of the database server, into which you can attach files "on the fly", without a real need for a fully managed SQL environment. You probably bumped into it if you have used the default setup for MVC or ASP.NET where you tried to use membership or other services. ASP.NET created a .MDF and .LDF file for you in the App_Data directory automatically. These are actually SQL Server Express User Instance databases.

If you ever checked the ConnectionString, it will contain a |DataDirectory| directive (and the term User intance=true. At runtime, the ASP.NET runtime resolves this to point into the App_Data folder of the application. The SQL client runtime of .NET is able to connect up this file into the user instance and use it, without any user action needed. It can also create it, if it does not exist.

While ASP.NET provides this behavior for its own databases by default, there is nothing stopping us from using the same feature with our custom application databases.


Create a missing database

When I put code into source code control, I rarely put it actual .MDF and .LDF files (databases). Instead, usually an .SQL script goes in there that can create my database. However, since LINQ has the neat feature to create the missing database, why not use that? This way I could make my project create the database it needs by itself, when starting up.

It would be ideal for distributing demos and examples. The person who opens it up, just needs to start it. Visual Studio self hosts the web application in its own web server, the database is created in the SQL Server Express User Instance, and it just starts working.

It is all very simple in theory, until you want to call LINQ's CreateDatabase() on a LINQ model that has a ConnectionString with the |DataDirectory| variable. I used CreateDatabase() succesfully before with regular SQL server databases. But when I tried the user instance approached, it failed.

My first try was the following code:

MyDataContext ctx = new MyDataContext( connString )
if (ctx.DatabaseExists() == false)
{
    ctx.CreateDatabase();
}


And what I got was an ArgumentException, that told me: Illegal characters in path.. Strange. I checked the callstack, which was:

   at System.IO.Path.CheckInvalidPathChars(String path)
   at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength)
   at System.IO.Path.GetFullPathInternal(String path)
   at System.IO.Path.GetFullPath(String path)
   at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.CreateDatabase()
   at System.Data.Linq.DataContext.CreateDatabase()


I checked everything, but all seemed to be fine.

I then tried substituting the actual path in the connection string, and my code worked. So what is going on?


Bug in LINQ DataContext

LINQ DataContext uses its own SQL wrapper, and that wrapper has a bug. It cannot resolve the |DataDirectory| constant. I used to .NET Reflector to verify this. Sure enough, the System.Data.Linq.SqlClient.SqlProvider class retrieves the AttachDbFilename entry from the connection string, and then uses it directly. So if you have |DataDirectory| in there, you are out of luck: an exception will inform you of this :)

Luckily, you can retrieve the value of the DataDirectory entry from the current AppDomain. So you could do the substitution yourself, pass the corrected connection string to the DataContext and create the database. Voila!


DataDirectory

So first, we need the DataDirectory entry. We can use the following code to retrieve it from the current AppDomain:

string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();


Putting it together

So I ended up writing the following method into my Global.asax.cs file:


        private void EnsureDatabase()
        {
            string connString = null;
            connString = global::System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;

            if (connString.Contains("|DataDirectory|"))
            {
                string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
                connString = connString.Replace("|DataDirectory|", dataDirectory);
            } 

            using ( MyDataContext ctx = new MyDataContext( connString ) )
            {
                if (ctx.DatabaseExists() == false)
                {
                    ctx.CreateDatabase();
                }
            }
        }


This code loads my connection string and if it finds the |DataDirectory| directive in there, it will replace it with the DataDirectory value from the AppDomain. It then fires up an instance of the DataContext and makes sure the database exists. Sure enough, this works (except ... see below).

This code can be called in Global.asax.cs in the Application_Start() method. After this, whenever you run the application and it finds the database is missing, it will create it. You would still need to populate it with initial data, if that is a requirement, because the database will be empty of course.


Multiple user instance databases

While testing the above problem, I replace the DataDirectory variable by hand first, tried it that way, and it worked. I then stopped the web server, deleted the created files and started playing around. I bumped into a problem when I then wanted to create the files again. As if SQL server believed the files existed, although I deleted them. As it turns out, User Instances are not as simple as they sound. There is a slight problem when you want to attach a database with the same path into the user instance that already existed. I wrote a separate blog post about that. See it here.



Variations on Http Handlers   (ASP.NET)   
HTTP handlers (classed that derive from System.Web.IHttpHandler) are a wonderful way to add richness to ASP.NET applications. They can also be used to serve custom dynamic content (say RSS feeds) or images, in addition to regular ASPX pages.

This article will introduce four different ways you can use HTTP handlers. The end result is the same, but I hope you will also find that by exploring different ways of using them you will also gain a better understanding of how things work. I will also show a typical error when using HTTP handlers from assemblies that are stored in the Global Assembly Cache (GAC).


When to use HTTP handlers?

I commonly use HTTP handlers to serve pictures from Web applications. Why would I need that? Pictures are often manipulated before being sent to the client. Such manipulation can include adding a watermark, resizing or applying other image transformations and manipulations. By applying these dynamically, I do not need to modify the original images: the application dynamically applies these modifications, and sends the modified content to the client. A good example could be generating thumbnails for an image gallery. Why bother doing this beforehand, when your application can just as well do it dynamically.

Of course usually the result can be cached, to improve performance - all transformations in an image gallery for example can be cached, because they will be the same, regardless of visitor. But it is not only image manipulation that can be achieved. If you have your images stored in a database, those too can be published in a web application by using HTTP handlers.

And handlers are not restricted to images, any content can be served using them. In fact (in case you do not know) the way ASP.NET serves ASPX pages is by the way of HTTP handlers. The Page class itself implements IHttpHandler that gets loaded and called for all pages with the .ASPX extension.


The Greetings Picture

Before we begin with the actual handlers, I want to show a very simple image manipulation class. What this does is create a new 640x120 sized bitmap with some greeting text written into it. It clears the background with white and writes in black Arial letters onto the surface. This is a very simple example, but you could do any image manipulation here.
using System.Drawing;
using System.Drawing.Imaging;

namespace MyLibrary
{
    public static class ImageBuilder
    {
        public static Image CreateGreeting(string name)
        {
            Bitmap bmp = new Bitmap(640, 120, PixelFormat.Format32bppRgb);
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.FillRectangle(Brushes.White, new Rectangle(0, 0, 640, 120));
                g.DrawString(string.Format("Hello {0}!", name), new Font( "Arial", 28 ), Brushes.Black, new Point(10, 10));
            }
            return bmp;
        }
    }
}

This piece of code will be used by all of the examples I will present.

To begin with, create a new ASP.NET Web Application (project), and add the above code to the project (ImageBuilder.cs). Also note that I have tested the examples with VS 2010 and .NET 4.0.


The traditional code behind .ASHX

The easiest and fastest way to create an HTTP handler is by selecting Generic Handler to be added to the project. This will create an .ASHX file and an .ASHX.CS file. Whenever you request the .ASHX file, the code-behind file will be invoked. However, in this case there are no controls, there are no predetermined content - you are in charge what you return.

Normally you override the ProcessRequest() method, and return any content from within there. Now that you have create your Web Application project (where you saved ImageBuilder, see above) add a new Generic Handler to it. Call it Handler1. This will add Handler1.ashx and Handler1.ashx.cs. You do not need to modify the ASHX file for now (we will get to its contents later). Now add the following code to the code behind file:
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;

namespace HttpHandlerTesting
{
    public class Handler1 : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "image/jpeg";

            string name = "Anonymous";
            if (context.Request.QueryString["Name"] != null )
            {
                name = context.Request.QueryString["Name"];
            }
            Image img = MyLibrary.ImageBuilder.CreateGreeting(name);
            img.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }

        public bool IsReusable { get { return false; } }
    }
}

AS you can see the class is derived from IHttpHandler. I will ignore the IsReusable property here, you can read more about that in MSDN.

This code will generate an image with a greeting to either "Anonymous" or to the name specified in the QueryString parameter Name. It will then return this image in the response. Notice that the ContentType of the response is set manually to the MIME type of JPG images. This is needed so the browser can interpret the response. After this is done, the image is written to the [n]OutputStream of the response, thus sending the JPG data back to the client.

Try invoking it by starting your application and navigating to Handler1.ashx?Name=Lenard. This will return an image with the text Hello Lenard!. (because the image contains white background and black text, it might not be obvious it is an image. Feel free to use a tool like Fiddler to verify it is indeed a JPG file! Alternatively, you could try to draw colorful lines and shapes in the background, but I leave that exercise to you :))

As you can see we only needed to add some files to the project to have a very simple handler. But there are more ways to use handlers, so let us process to Step #2.


A single .ASHX file

So now that you saw the code-behind version, lets merge the two files into a single file. But before we get started, lets examine the ASHX file. Open the Handler1.ashx file. Simply double clicking might not work, right click on it and select view markup in this case.
<%@ WebHandler Language="C#" CodeBehind="Handler1.ashx.cs" Class="HttpHandlerTesting.Handler1" %>

The ASHX file is very similar to that of an .ASPX or .ASCX file. But it does not declare a Page, it declares a WebHandler. The file is empty except for this one line, which declares the class to use and the code behind file where the class can be found.

Now to make a single file handler, add Handler2.ashx to the project. Maybe the easiest way to achieve this is to select to add a Text document to the project in Visual Studio, and then type Handler2.ashx as the name.

<%@ WebHandler Language="C#" Class="Handler2" %>

public class Handler2 : System.Web.IHttpHandler
{
    public void ProcessRequest(System.Web.HttpContext context)
    {
        context.Response.ContentType = "image/jpeg";

        string name = "Anonymous";
        if (context.Request.QueryString["Name"] != null )
        {
            name = context.Request.QueryString["Name"];
        }
        System.Drawing.Image img = MyLibrary.ImageBuilder.CreateGreeting(name);
        img.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
    }

    public bool IsReusable { get { return false; } }
}


It is really not that different from the original version. We simply removed the CodeBehind attribute and included the class definition in the body of the ASHX file. Is this solution better than the first? I will let you decide that :)


Code in another assembly

A more complex system could include the handler logic (the code) in another assembly, separate from the actual Web pages. In this case you can still use the .ASHX file to register your handler. I find this easier to do than getting dirty and registering your handler in the Web.config file - rest assured the next section will show you how to to that.

To proceed, add a Class Library to the Solution, we will call it MyLibrary. You will have to move ImageBuilder to this new library. Then, proceed to add a new C# class to this new library, which we will call Handler3:

using System.Drawing.Imaging;
using System.Web;

namespace MyLibrary
{
    public class Handler3 : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "image/jpeg";

            string name = "Anonymous";
            if (context.Request.QueryString["Name"] != null)
            {
                name = context.Request.QueryString["Name"];
            }
            System.Drawing.Image img = ImageBuilder.CreateGreeting(name);
            img.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }

        public bool IsReusable { get { return false; } }
    }
}


As you can see this is pretty much the same code we have been using before. Now comes the modification to the .ASHX file. Add Handler3.ashx to the web project:

<%@ WebHandler Language="C#" Class="MyLibrary.Handler3" %>


Here we specify the namespace and the class. From here there are two ways to proceed.

In case MyLibrary is just your regular .NET class library (no strong names, etc), you can just add a reference to it to your web project. This will include MyLibrary.dll in the bin\ folder of the web application. It will also take care of the rest, and the above handler delcaration will work.

However, if your library has a strong name and you store it in Global Assembly Cache, you will get an ASP.NET error saying it does not find the library. As it turns out, for automatic binding to work the class that you refer to in the Class attribute must be found in an assembly that is in your bin\ folder.

This error happens even if you have created a reference to the library.

To solve this problem, we simply need to add a reference to the assembly into the .ASHX file:

<%@ WebHandler Language="C#" Class="MyLibrary.Handler3" %>
<%@ Assembly Name="MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4433e4487bd68da" %>


Of course make sure you use the correct identifier for the particular assembly you are working with. This will solve the problem with the reference, and now our handler works even from the GAC.

You might wonder when can you run into this problem? In SharePoint if you want to use an ASHX file and the handler code in a DLL, you will probably end up having this problem.


Handlers in Web.config

Having an ASHX file will make it easy to use handlers, because you do not need to register them. You can however register your handlers in Web.config. This gives you finer control over when your handler is called, what extensions it will serve, etc.

To finnish this example let's create the fourth version of the handler. Let's add this to the external class library project - MyLibrary - as well. We will call this class Handler4.

using System.Drawing.Imaging;
using System.Web;

namespace MyLibrary
{
    public class Handler4 : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "image/jpeg";

            string name = "Anonymous";
            name = System.IO.Path.GetFileNameWithoutExtension(context.Request.Path);
            System.Drawing.Image img = ImageBuilder.CreateGreeting(name);
            img.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }

        public bool IsReusable { get { return false; } }
    }
}


In this handler I changed the name fetching code. Instead of the QueryString parameter, we use the name of the request. Without extensions. As you will soon see, when we are registering a handler in Web.config, we can use a "star" name, and are not locked into a single name.

Now comes the change to Web.config. You will have to register the handler in either of two places (or perhaps both).

If you use IIS 6 or the Development Web Server in VS2008/2010, you will need to add this to the system.web section:

  <system.web>
    <httpHandlers>
      <add verb="GET" path="*.jpg" type="MyLibrary.Handler4, MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4433e4487bd68da"/>
    </httpHandlers>
  </system.web>


If you use IIS 7, 7.5 , you will need to add this to system.webServer:

  <system.webServer>
    <handlers>
      <add name="MyHandler" verb="GET" path="*.jpg" type="MyLibrary.Handler4, MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e4433e4487bd68da"/>
    </handlers>
  </system.webServer>


In either case you tell ASP.NET to map all request to *.jpg (that is all jpg files) that are HTTP GET requests to our handler. If you now request Lenard.jpg from the server, you will actually get our dynamic greeting image, which reads Hello Lenard!.

There is nothing preventing you from simply specifying "Handler4.ashx" as the path attribute, but let's admit that would not be as much fun :)


Conclusion

HTTP handlers can be a lot of fun, and they are very lightweight (compared to the regular ASP.NET Page pipeline). With them, you can completely customize the way your application functions, because as you saw you can even return dynamic content when a "regular" file, like a .jpg image is requested from the server. As you saw, there are many ways to use a handler, and you should pick the one that fits the situation at hand best.

TechDays 2010 Presentation video (Finnish only)   (ASP.NET)   
My slides for my presentation at TechDays 2010 Finland are available online (I am a little bit late with this news for the blog :) ). You will need to understand Finnish to enjoy them :)

Web sovellusten liikenten debuggaus ja testaus

(my slides and demo solution are available via my previous blog post)

You can also find other presentations recorded (part in Finnish, part in English) on the Codezone portal. You will need Silverlight to watch the videos.

Silverlight 3 designer (preview only) in Visual Studio 2008   (ASP.NET)   
I have encountered at least one person and read from one book, that Silverlight 3 does not provide a visual designer in Visual Studio 2008. Silverlight 2 had a preview only "designer", that would show the changes you made to the XAML in real time. The person/book suggested this would have been gone with Silverlight 3.

This is of course not true. Although a carefully hidden feature, it is very easy to enable it. After that you are not required to build and run your Silverlight application to see a preview of it.

Here is what VS 2008 looks like after you installed the Silverlight 3 tools:

a picture in a bl0g

I would like to call your attention to the very bottom, where you can see double lines. I drew a red rectangle there in the image above. When you move your mouse very carefully there, it will switch into a splitter cursor. Sometimes it will just flash for a second, but move your mouse very gently, and you can find it there (it is probably only 1 pixel thick, so accelerated mouse might have problem finding it).

Now click and drag, and voila!

a picture in a bl0g

Now simply click resume loading the designer. And you now have your full XAML preview only designer. You can zoom in and out and check out how your XAML page/control will look like.

While you cannot use it to actually drag and drop controls, it still saves a lot of time when you do not need to compile and run to see the end results.

a picture in a bl0g


ASP.NET MVC 2 released   (ASP.NET)   
ASP.NET MVC 2 was released today. More details in ScottGu's blog:

ASP.NET MVC 2 Released

ASP.NET Page Lifecycle   (ASP.NET)   
I have seen many graphical representations of the ASP.NET Page Lifecycle events. Some were more complete than the next. But now I found a great textual representation, that is easy to print and use.

Unwinding the page lifecycle events

Tampering with ASP.NET disabled controls   (ASP.NET)   
Ever disabled a control because of say authorization reasons? For example, some users might not have the necesarry rights to edit some detail of a data item, while other users can edit it. If you solve this scenario by simply using disabled controls, without any further data check when you update the values on the server side, you might be surprised that it is not really an effective way.

You see, the values sent to the server control can be tampered with. There are really good tools to do this, for example, TamperIE for Internet Explorer. Similar tools are available for Firefox as well as extensions.

All of these tools allow you to change (read: insert, delete or update) any form values that are sent when doing an HTTP POST request.

Now under normal conditions when you set a TextBox to disabled, it will not send the value to the server. This is actually a feature of the HTML standard, which says that disabled controls should never send their values when submitting a form.

However, with TamperIE, you can insert values into the POST value list. And ASP.NET will read the values from this list, regardless of the control being disabled or not. If you simply update your data item with the values from controls, your application might be vulnerable to this kind of spoofing attacks.

Example

Suppose we have the following ASP.NET code:

a picture in a bl0g

You can see two text boxes, one of them disabled. When you press the button, the following code is executed:

        protected void Button1_Click ( object sender, EventArgs e )
        {
            labelEnabled.Text = txtEnabled.Text;
            labelDisabled.Text = txtDisabled.Text;
        }


The code feeds the values from the text boxes into labels, but it could just as well update some data item and save the changes into a database.

Under normal conditions the labelDisabled control will have the "constant" text that was put into the txtDisabled text box, by the server. However, start playing with the parameters, and you can change that value as well.

After you have installed TamperIE, when you do a form post, the following window will appear:

a picture in a bl0g

This window allows modifying the parameters that are to be sent to the server. You can then choose to send the original or the altered values. In the screenshot above you can already see that I added the txtDisabled parameter to the collection of parameters, and set its value to Hello world!. As a result my labelDisabled will display that value (also the text box) after I submit the values to the server and get back an updated page.

Solution?

There are two solutions how you can avoid this kind of attack.

First, you can just not use a TextBox control. This might or might not be an available solution in your case. Using a Label will prevent invalid values from entering into the server by altering parameters.

But a better way is to always validate any data received on the server side. If the text box was disabled because the user is not authorized to modify that value make sure you never use or update that value when the POST occurs.

MVC?

Can this affect applications based on the ASP.NET MVC Framework? The short answer is: yes it can. If for example you use the UpdateModel method when processing data, it will read the values from POST paremeters. As a result, tampering with the POST values will also affect what gets updated into the model. In fact in a way it is much easier to trick the system into processing parameters - given that you know what to name them.

Dangers of comments with ASP.NET   (ASP.NET)   
Ever wanted to comment out a section of your code - temporarily or for a longer time - in an .ASPX page? If you have not used server side comments, you might be surprised at the ends results.

There is something to remember concerning comments that you might not be aware of when commenting out code in an .ASPX or .ASCX file. When you use HTML comments, that is, <!-- ... -->, that code will not be commented out from an ASP.NET point of view. The code will be parsed. If you have controls there, they will be available to the page. If you have text there, it will be visible on the client side. This can pose a security risk and can lead to defective programs (as a worst case scenario).

A much better way is to use server side comments. These are available when you enclose the section in <%-- ... --%>. This section of code will not be visible on the client side, and it will not be parsed by ASP.NET.

Suppose you have the following in your ASPX page:

a picture in a bl0g

As you can see there are two comments after one another. To the casual observer, there is no real difference: both are comments.

Now check out what the generated HTML looks like:

a picture in a bl0g

As you can see the server side comment in the <%-- ... --%> form is completely hidden and not visible. However, the normal HTML comment was parsed and a control was rendered. Not only that, the control is available in server side code as well:

a picture in a bl0g

So next time you want to comment out something - for whatever reason - make sure you remember to do it right.

Of course I have to note that in any real world scenario you would not commit/checkin commented code into version control. That defeats the whole idea of version control. If you want to remove something you can be sure it will still exist in a prior version.

Routing and Web Part Zones revisited - with Visual Studio 2010 Beta 2   (ASP.NET)   
I wrote earlier about how ASP.NET Routing does not really work with Web Part Zones. Both are interesting and useful features on their own, but they do not work nice together. You can read more about it here:

.NET routing and Web Part Zones == an impossible mix

I had Visual Studio 2010 Beta 2 and the .NET Framework 4 Beta 2 installed recently, so I thought I would give it a try and see if this bug has been fixed.

Unfortunately it seems that the developers at Microsoft have been working on other interesting features, because the example that I presented before does not work in VS2010. Of course this is only a beta release, but if this hasn't been fixed to this point, I think it will remain unfixed.

.NET routing and Web Part Zones == an impossible mix   (ASP.NET)   
Ever used Web Part Zones? How about ASP.NET Routing (introduced in .NET 3.5 SP1)? Both are interesting features. But try them together, and you are destined to fail. The reason for this is probably because different teams implemented them, and no one thought they would be using it together. Doh?! :-\

I bumped into this problem when I wanted to add Web Part Zone support for my rpgWiki application (a wiki we use for roleplaying). I was greeted with a nasty exception:

HttpException (0x80004005): The file '/WikiWeb/articles/Helsinki_by_Night.aspx' does not exist.

Here the /WikiWeb is the path to the application on my development server, and the rest of the path is a non existing virtual file. Without the Web Part Zone code, this works just fine, ASP.NET Routing will find the actual physical file and execute that.

Looking at what went wrong I found the following code fragment was being executed. The actual exception happened when invoking ToggleScope():

                if ( WebPartManager1.Personalization.Scope == PersonalizationScope.User )
                {
                    WebPartManager1.Personalization.ToggleScope ();
                }

In my rpgWiki project I did not want to provide per user customization. So whenever I saw the User scope, I wanted to change that to Shared scope. So why the hell do I get this exception all of a sudden?

Well, it turns out (after looking at the call stack and digging around with Reflector) that ToggleScope will change the setting, and after that execute a Server.Transfer() to the same page. In "classic" Web Forms without routing this is not a problem, but it turns out the ASP.NET team did not upgrade Server.Transfer() for routing. So it tries to execute the same address where the original request came to, and because it is a virtual path only understood by routing, it will not work.

I was able to speak with Scott Galloway from the ASP.NET team at a conference. He also confirmed this to be a bug, but couldn't say if it would be corrected.

Of course this means that not only Web Part Zones will not work, but rather Server.Transfer() will never work when you want to transfer to a page that does not exist and would need routing.