Lifting an ASP.NET MVC 1.0 project to Visual Studio 2010

I have a pet project (several actually, but let’s stick to one of them). It’s called Önskelistemaskinen, and is a web application for keeping track of the wish lists of my family members. It’s build in ASP.NET MVC with a Linq-to-SQL backend (loosely modelled after Rob Conery’s Storefront project), and naturally grossly overdesigned for an application with a target audience of about 10 people.

Anyway, I started working on this when the first beta of ASP.NET MVC came out about a year ago, and with every new release I have had to rework lots of it. So when both Visual Studio 2010 beta 2 and ASP.NET MVC 2 preview 2 came out almost simultaneously I figured, what the hell, time for another rewrite!

My first approach was to just open the project in Visual Studio 2010. It seemed very helpful, offering to convert the project to VS2010. But on closer inspection, I found that it had converted all of the projects except for the actual web project. So no luck.

I had read a blog post by Scott Hanselman about converting a ASP.NET MVC 1.0 project to 2.0 (for Visual Studio 2008, though), and also thought I had seen something pass by about an application doing that for you. I figured that might be the way to go. Just to be sure I threw the question out on Twitter, and within minutes I got an answer pointing to the conversion application.

I used the application and converted my 1.0 project to 2.0. Then I opened the project in VS2010 again, and this time the conversion wizard gladly converted my web project to VS2010! Now, I had a few other problems, since I hade used a few features in MVC Futures library, which didn’t seem to work anymore. But after fixing these, everything seems to work fine (by the way, I noticed while writing this post that MVC Futures also has a new release, so a better idea might have been to use that one. I’ll check it out tonight).

In conclusion, to get your VS2008/ASP.NET MVC 1.0 project to work in Visual Studio 2010, follow these steps:

  1. Upgrade the project to ASP.NET MVC 2, preferably using Eilon Lipton’s migration tool.
  2. Open the project in Visual Studio 2010, and let the conversion wizard work its magic.
  3. ??
  4. Profit!

Update: Turns out that Phil Haack wrote a post describing this sometime between my attempts to get it working yesterday evening and my writing of this post this morning.

In SQL, null is not != 1

Had an interesting error today. An database query that should have returned thousands of lines returned nothing. Turned out it was due to how the inequality operator works in SQL. In most programming languages, like C# or java the inequality operator handles null, so for example the following code (although extremely stupid) will work.

1
2
3
4
5
6
bool? nullValue = null;
bool? trueValue = true;
bool? falseValue = false;
Console.WriteLine((true != nullValue) );
Console.WriteLine((true != trueValue) );
Console.WriteLine((true != falseValue) );

This will produce the result True, False, True, since true really isn’t equal to null.
In SQL, however, this is not the case. Consider the following SQL query:

1
2
3
4
5
6
7
8
-- TestTable data
-- id name isTrue
-- 1 test 1
-- 2 test 0
-- 3 test NULL

select * from TestTable
where isTrue != 0

If you’re not familiar with SQL, you might think that this would return two rows, the one where isTrue is 1 and the one where isTrue is NULL. This is obviously not so, otherwise I wouldn’t have written this post. You only get the one where isTrue is 1. This is due to the fact that in SQL, the inequality operator (!= or <>) does not work on null values. So in order to get both lines, you would have to modify the query like this:

1
2
select * from TestTable
where isTrue != 0 or isTrue is null

Of course, in this case, this is not the correct solution. A column that is obviously Boolean should not allow null values at all! This was also the case in the non-working query I came across. So the moral of the story is:

Never allow null values in for boolean columns!

Mime type for Android apps

I recently got an Android phone (a HTC Hero, to be specific), and of course I felt the need to develop applications for it. I have a few in mind, and I’m sure I will dwell on that in upcoming blog posts. One thing, however, I learned immediately: In order to get the phone to install your app from a web server, you need to have the correct mime type for it.

It turns out that the correct mime type for an .apk file is

application/vnd.android.package-archive

You also need to change the settings to allow installation of programs that doesn’t come from Android Market. This setting is found in* Settings > Program, and is probably called “Unknown sources*” in English (it is definitely called “Okända källor” in Swedish).

New place, new look, same me

I started blogging on the Dropit Labs blog about a year ago, and I have kind of gotten used to it. But since I no longer work at Dropit, and thus am unable to keep writing there, I felt the need to create another place to write my posts about web development. The simple solution was obviously to start my own blog, and this is the result! Since I didn’t want to start all empty, I have copied most of my posts on the labs blog (except for a few that was only about Dropit stuff).

I have decided to run this blog on Subtext, but the choice was not easy, I can tell you! I knew that I wanted to host the blog myself, and not use a hosted blog engine like Wordpress or Blogger, since I want to be able to tweak the blog. I also made the pragmatic decision that the engine had to be written in C#, to lower my bar for actually modifying the code. I definitely did not want it to be written in PHP, because that really makes my skin crawl.

So basically, I had to look for a good .net blog platform, that was also open source. Some research (let’s call it research, but it was really just googling) yielded four candidates: BlogEngine.NET, dasBlog, AtomSite and Subtext. Initially, I though AtomSite looked very promising, especially as it is written in ASP.NET MVC, which I really like. Unfortunately I found it still lacking a bit too many features. BlogEngine.NET was the platform we used for the labs blog, and although that worked out ok, I thought it would be more fun to try something else. I wasn’t 100% happy with it anyway. So basically it came down to dasBlog or Subtext, and in the end, I just felt that Subtext had a little more umpf than dasBlog.

Finally, I just realised that I have mentioned my previous employer no less than 3 times in this post. In the name of fairness I feel compelled to mention my current employer an equal amount of times now. Active Solution. Active Solution. Active Solution.

So, there.

Until next time, I remain your humble servant.

Subtle differences

This post was originally published on *http://labs.dropit.se/blogs.*

Today I hade the dubious pleasure of having to work with an old EPiServer 4 site, and having to deploy it to IIS7 on a Windows 2008 Server.

In order to make everything work in EPiServer 4, you need to make sure that all 404-request are redirected to /Util/NotFound.aspx. On my development machine, which runs Windows 7, I accomplished this by adding the following code to web.config:

1
2
3
4
5
6
<system.webServer>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/Util/NotFound.aspx" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>

Since both Windows 7 and Windows 2008 Server runs IIS7, you would think that this should work on the server as well. But when I ran a particular URL that needed the redirection to NotFound, I only got the following error message:

The page cannot be displayed because an internal server error has occurred.

Nothing else. Nothing in the log files, nothing in the event log. Hmmm.

After fiddling around for a while and trying to figure out what was wrong, I tried going into the Error Pages feature in IIS Manager on the server, and suddenly got the error message saying:

This configuration section cannot be used at this path. This happens when the section is locked at a parent level. Locking is either by default (overrideModeDefault=”Deny”), or set explicitly by a location tag with overrideMode=”Deny” or the legacy allowOverride=”false”.

What this basically means is that I can’t use the <httpErrors>-section in web.config, because the machine settings says that I can’t. Now, the settings for IIS7 can be found in the file applicationHost.config, located in C:\Windows\System32\inetsrv\config. A look in this file on both the server and on my machine showed a subtle difference:

1
2
3
4
5
<!-- Windows 7 -->
<section name="httpErrors" overrideModeDefault="Allow" />

<!-- Windows 2008 Server -->
<section name="httpErrors" overrideModeDefault="Deny" />

For some reason, the default configuration on Windows 2008 Server doesn’t let you override the httpErrors-configuration in web.config, while the default configuration on Windows 7 does. I’m not saying that either one is more correct that the other, but if it had been the same on both it would have saved me a couple of hours of work today. Sometimes subtle differences can cause a lot of work…

Most misleading error message ever?

This post was originally published on *http://labs.dropit.se/blogs.*

Sometimes .NET error messages are helpful, sometimes they are not. But worst of all are when they are outright misleading! Like the one I came across today.

I was trying to programmatically register a ASP.NET Ajax ScriptManager in a web control, and as the webcontrol was already overriding OnPreRender, I figured “what the heck, I’ll just put it there”. So, I basically wrote this code:

1
2
3
4
5
6
7
8
9
10
11
12
protected override void OnPreRender( EventArgs e )
{
RegisterScriptManager();
base.OnPreRender( e );
}
private void RegisterScriptManager()
{
if (ScriptManager.GetCurrent( Page ) == null)
{
Page.Form.Controls.Add( new ScriptManager() );
}
}

Now, as it turns out, OnPreRender is not a particularly good place to try to modify the control collection of the page. When I tried to run the page, I was greeted by this friendly error message:

image.axd

Ok, so the control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases. Really? What events does that leave us with? Lets see, override…

image2.axd

Whoops, turns out the only events available are OnDataBinding, OnInit, OnLoad, OnPreRender and OnUnload. Exactly the ones that the error message told me not to use. Well, since the error message explicitly told me not to use them, I suppose I can’t.

The next 30 minutes or so I spent trying to find another (not too complicated) way to put my ScriptManager in the page, I also googled (actually, binged) quite a lot, and found a post that seemed to modify the control collection during the Init phase… That wouldn’t work, would it? I said to myself, what the hell, it can’t hurt to try, and changed my code to this:

1
2
3
4
5
protected override void OnInit( EventArgs e )
{
RegisterScriptManager();
base.OnInit( e );
}

Ctrl-Shift-B. Alt-Tab. F5. Wait. Wait some more… Lo and behold, it works!

So, it seems you can modify the control collection during the Init phase, even though the error messages explicitly tells you that you cannot! WTF! Thank you very much .NET Error Message Team, whoever you are, for wasting 2 hours of my day (yeah, after I had wasted 30 minutes on this error, I wasted another 1½ hour writing this blog post :-))

Facebook Comments in EPiServer

This post was originally published on *http://labs.dropit.se/blogs.*

Facebook Comments is a very useful widget for Facebook Connect, the integration platform for Facebook, allowing you to place a comments box on your web pages. As it uses the Facebook connect platform, it lets the users sign in with their Facebook accounts as well as publish their comments to their FB feed, making this a powerful marketing tool as well.

Not that it is extremely difficult to integrate the comment box in your EPiServer site, but we thought it would be a good idea to make it even easier. So behold, the “Facebook Comments for EPiServer CMS” module (yeah, I know, I should work on the name) was born!

Instructions

In order to use the comments box, you first need to create a basic Facebook App. Name this anyway you like, for example JohanEPiComments. After you have created the app, set the callback url for your site (Canvas –> Canvas Callback URL). A public url is not needed, but if you are developing on your local machine, you can’t use “localhost”, but rather something like “myepisite.local”.

That’s it, your application is set up. Now, take note of your API key and your secret key. These are needed later.

Copy the binary files from the zip file below to your bin folder, and add the following lines to you web.config (or just put the highlighted line at the appropriate position):

1
2
3
4
5
6
7
<system.web>
<pages>
<controls>
<add tagPrefix="Dropit" namespace="Dropit.FacebookComments" assembly="Dropit.FacebookComments"/>
</controls>
</pages>
</system.web>

You also have to add a “cross-domain receiver file” to your application root folder (probably a good idea to include it in your project), in order to enable Facebook to run scripts on your page. Currently you can download this file here: http://www.somethingtoputhere.com/xd_receiver.htm.

After this, you have to add some properties to you start page in EPiServer:

image.axd

The FacebookAPIKey and FacebookSecretKey properties are, of course, where you enter the API key and the Secret key from your application. The FacebookCommentXidPrefix is a prefix for the unique ids for every page comment box (xid). Facebook Comments normally uses the url of the page for this key, but this makes it difficult if your pages are accessible on several domains (i.e. www.dropit.se and dropit.se). Instead you could use the prefix “dropitse”, and make it domain independent.

After settings this properties, all you have to do is to add a web control to the pages that you want to have comments on:

1
<dropit:commentsblock runat="server" Width="500" NumPosts="10" />

The web control accepts all attributes that are described on http://wiki.developers.facebook.com/index.php/Fb:comments_%28XFBML%29, except “xid”, which is automatically created for the page. All are optional. Note: The commentsblock control automatically adds a script reference to the head-section of the page, but for this to work the head tag needs to be runat=”server”. If, for some reason, you don’t want your head-element to be a server control, you could add the script reference manually, like this:

1
2
3
4
5
6
7
8
9
<!-- head as a server control - no need for the script reference -->
<head runat="server">
...
</head>

<!-- or you can register the script manually -->
<head>
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" type="text/javascript"></script>
</head>

An extra feature in this plug-in is the ability to get the number of comments for a specific page without actually loading the comments box. This is done by calling FacebookUtility.GetCommentCountForPage(), which takes a PageData object as variable. This feature uses the Facebook Developer Toolkit, which is included in the zip file.

Disclaimer and licensing

No guarantees whatsoever are made for the functionality or usability of this code. It might eat your code and format your hard drive, but probably not. That said, if you have any questions or opinions, please post them as comments to this post.

This is released under the WTFPL license. Please modify as much as you want.
http://sam.zoy.org/wtfpl/
http://en.wikipedia.org/wiki/WTFPL

Download

Binaries: Dropit.FacebookComments_Bin.zip
Source code: Dropit.FacebookComments_Source.zip

*Update on repost on my new blog – just in case Dropit would do something stupid, like move or even remove the files linked above, I also made them available from my site:
Binaries: Dropit.FacebookComments_Bin.zip
Source code: Dropit.FacebookComments_Source.zip*

An Excellent Analytics Tool

Ever wished that you could extract the data from Google Analytics and process it in some powerful application like say, Microsoft Excel? Well, now you can!

Excellent Analytics is a simple Excel plug-in that let’s you import data from you analytics account straight into your spreadsheet. It has been developed as thesis work here at Dropit by our former intern Fredrik Johansson (great job!), and is available as open source at excellentanalytics.com, or if you want the source code at http://code.google.com/p/excellent-analytics/.

It is also being released as a part of our Labs project at http://labs.dropit.se.

Check it out!

Updated: Article on IDG

Windows 7 XP Mode is really nice

This post was originally published on *http://labs.dropit.se/blogs.*

As an early adopter of everything new (meaning if it isn’t beta it is not worth installing), I recently installed Windows 7 RC on my laptop, and yesterday I also installed Windows XP Mode, or XPM. XPM is basically an extension of Virtual PC, and a new Virtual PC beta version, that allows you to run XP applications outside of the virtual machine, just like normal applications.

image.axd

This is really useful e.g. for testing things in IE6, or older versions of Firefox. The only working way of running IE6 on Vista or Win7 is in a virtual machine, but switching between the virtual machine and your normal environment is a hassle. But now I can just start “Internet Explorer (Virtual Windows XP)” from start menu in Windows 7, and get an XP/IE6 window right beside my other apps.

The only thing that bugs me is that the taskbar icon shows a virtual pc icon instead of the IE6 icon.

icon_screenshot

Security flaw in EPiServer plugins?

This post was originally published on *http://labs.dropit.se/blogs.*

A colleague of mine - let’s call him Erik Nilsson, since that is his name - recently came across a potential security problem when creating your own edit och admin plugin to EPiServer. Unfortunately, he’s too shy to write a post about it, so I’ll relay the information. If you create a plugin like this:

1
2
3
4
5
6
7
8
9
10
[EPiServer.PlugIn.GuiPlugIn(
Area = EPiServer.PlugIn.PlugInArea.AdminMenu,
DisplayName = "Plugin name.",
Description = "Plugin desc.",
Url = "~/plugin/myplugin.aspx",
RequiredAccess = EPiServer.Security.AccessLevel.Administer )]
public partial class MyPlugin : EPiServer.UI.SystemPageBase
{
//...
}

You might think that this plugin in only accessable to users with administration right. This however, is only the case if you access it through the admin mode. If you access the page directly, i.e. by using the url http://somesite.com/plugin/myplugin.aspx, you can access it without even having to login. Seems EPiServer only checks the RequiredAccess in the admin or edit mode.

So what you need to to in order to secure your plugin is to set required access for the “plugin” location in web.config:

1
2
3
4
5
6
7
8
<location path="plugin">
<system.web>
<authorization>
<allow roles="WebAdmins, Administrators" />
<deny users="*" />
</authorization>
</system.web>
</location>

Bug or working as intended? I don’t know, but it’s important to keep in mind either way.

By the way, I’m trying out a new syntax hightlighter. Like it? It’s this one. The old one is still available as well, but it seems to be more happening with this one.