Troubleshooting TeamCity MSBuild error ASPPARSE: Could not load type

July 15, 2010

I’ve recently been experimenting with automated builds for an ASP.NET MVC project with the following setup:

  • Build Server: TeamCity 5.1.2
  • Build runner: MSBuild
  • Build project: Visual Studio 2010 Web Deployment Project
  • MSBuild/framework versions: .NET 4
  • Application details: ASP.NET MVC 2 Web Application .NET 4 project w/ various referenced projects and assemblies

I initially got TeamCity up and working with a Visual Studio 2010 Solution build runner and was successful in building my application, but I wanted to get it up and running with the MSBuild runner so I could pass along some targets and command line parameters like I could do when building the Web Deployment Project through msbuild.exe in a command window. After hours of troubleshooting, I finally have it working and if you’re having the same problem maybe this post will help.

Build errors

When I ran a build with the TeamCity MSBuild runner I kept getting the following error:

[Project "MyProjectName.wdproj.teamcity.patch.tcprojx" (TargetName target(s)):] /MyProjectName.csproj/global.asax(1, 0): error ASPPARSE: Could not load type 'MyProjectName.MvcApplication'.

Go ahead and Google that. If you got here from a search similar to “TeamCity ASPPARSE Could not load type”, we’ve read all the same articles by now, and if you’re in the same situation as me none of them seemed to help.

The error “Could not load type” hints that perhaps TeamCity can’t find the appropriate DLL and there are some discussions on the matter, though with completely different scenarios. None of these fixed my problem.

BuildInParallel=”true”

It wasn’t until I ran across this thread on the ASP.NET forums where someone suggested including this BeforeBuild target:

<Target Name="BeforeBuild">
    <MSBuild Projects ="..\WebAppProjDir\ProjName.csproj" BuildInParallel="true"  />
</Target> 

And my TeamCity build configuration now works! Why? I have no idea, and I’m sorry if you came here for a real understanding of it because I don’t have one yet.  The MSDN docs even state “BuildInParallel: If true, the projects specified in the Projects parameter are built in parallel if it is possible. Default is true.” Furthermore, it’s apparently meant to speed up build times in multi-processor systems, not have anything to do with the success or failure of a build.

Nevertheless, adding this target to my Web Deployment Project file was the only thing I could do to get TeamCity to play nice with my MSBuild runner configuration. I’m fairly new to TeamCity and MSBuild so I trust that I’m probably doing something (or ten things) wrong elsewhere. I’m learning as I go. Regardless, if you happen to have a similar problem, I hope this article may have helped.

Tags: TeamCity, MSBuild
Categories: Troubleshooting

App_offline.htm gotchas with ASP.NET MVC

July 12, 2010

You could be inadvertently exposing your visitors to unfriendly 404 and 403 errors when updating your ASP.NET MVC application, even after deploying an app_offline.htm file!

How app_offline.htm is supposed to work

The ability to take an ASP.NET application temporarily offline by uploading a file named app_offline.htm was a little known, undocumented feature of ASP.NET 2.0 until popularized by Scott Gu’s post about it back in 2005. How it works is simple, to quote Scott:

[If you place a file named app_offline.htm] in the root of a web application directory, ASP.NET 2.0 will shut-down the application, unload the application domain from the server, and stop processing any new incoming requests for that application. ASP.NET will also then respond to all requests for dynamic pages in the application by sending back the content of the app_offline.htm file (for example: you might want to have a “site under construction” or “down for maintenance” message).

Interestingly, this is the second most popular “hidden feature of ASP.NET” on Stack Overflow.

This technique works for traditional ASP.NET 2.0 web forms because typically every url on a site corresponds to an .aspx file. The application gets unloaded and the request for such a dynamic page results in the serving of a friendly “down for maintenance” type of message to any visitor accessing virtually any page of the site.

Try this with an ASP.NET MVC application though, and consider the potential horror:

403 - Forbidden

404 - File not found

(Note the 403 error occurs on the application root (“blog” in this case) and the 404 occurs on any MVC Controller Action “page.”)

Why this happens with ASP.NET MVC

Don’t believe me? Go ahead and drop an app_offline.htm file into your application root and… wait… what errors? Everything appears to be working as expected…

project directory site offline

Everything seems fine.

I’ll get to this in just a minute, but let’s consider a different scenario where we’re doing a major deployment and perhaps deleting everything including the web.config in the application’s directory first, leaving us with just a lonely app_offline.htm file. The result, alas:

empty directory with app_offline.htm  404 - file not found

What gives?

Let’s consider the latter scenario where we have an app_offline.htm file and nothing else in our application directory. Though this tells IIS to unload the application and serve up this file in place of dynamic resources such as .aspx pages, it doesn’t change the way it handles other resource requests, and without certain configurations in IIS and/or a web.config file (when present) your visitors may still see 404 or 403 errors.

403 – Forbidden: Access is denied.

If you don’t have “app_offline.htm” listed in the IIS Default Document configuration (and you have directory browsing turned off) you’ll get a 403 error when trying to access the root of a site. IIS simply tries to find the first match for a default document to serve up, and if it doesn’t find one it will return the 403.

You could simply add “app_offline.htm” to the defaut document configuration to get around this error. IIS will find it, and serve up your friendly offline page. Alternatively you could add any .aspx page (such as default.aspx – an empty file is fine) that is configured as a possible default document. This will clue IIS in that an ASP.NET resource is being requested and cause it to serve up the app_offline.htm instead.

404 – File or directory not found.

When you request a dynamic “MVC resource,” such as a Controller Action method with its inherent friendly url (eg. http://kurtschindler.net/blog/post/some-post-here) you’ll get a 404. Think about the consequences here. Even if your application root was showing a friendly “down for maintenance” page, many other potential visitors may be accessing other pages directly and being fooled into thinking they no longer exist!

Again, IIS knows not, and assumes you are requesting a default document in a directory that matches the url specified (eg. it’s looking for a default document under [root]\blog\post\some-post-here). Of course, no such directory or document exists. 404.

In both scenarios, IIS has no clue ASP.NET is involved and thus completely ignores the presence of the app_offline.htm file. So the solution is to tell IIS to runAllManagedModulesForAllRequests so it invokes ASP.NET which then serves up the app_offline.htm page.

The web.config solution

Add a web.config along with your app_offline.htm with just the bare minimum required setting:

<?xml version="1.0"?>
<configuration>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
    </system.webServer>
</configuration>

Now request any resource on your site again and the app_offline.htm takes over as expected!

empty dir with app_offline and web.config site offline

This web.config is required to tell IIS to enable all managed (ASP.NET) modules to run for all requests and therefore serve up the app_offline.htm for all requests.

In a lot of cases, you’ll likely be taking your site offline while retaining (or copying over instantly) your site’s web.config, and you probably already have runAllManagedModulesForAllRequests set to true or other modules present which dictate that ASP.NET should handle the request. You’ll be error free in this case, but if you ever remove the web.config during the outage you’re in trouble.

Conclusion

The app_offline.htm feature of ASP.NET is not the be all, end all, magical way to turn your entire application off in a friendly way for MVC applications. Because a lot of requests for an MVC application go to resources that first appear not to be managed by ASP.NET (friendly, extension-less urls), it’s vital that IIS be told to invoke ASP.NET for all possible requests, and this requires the presence of a web.config file stating as such.

If you are going to remove your application’s web.config file during site maintenance, you must also include a temporary web.config that specifies runAllManagedModulesForAllRequests=”true” along with the app_offline.htm file.

My bike ride around Manhattan

July 6, 2010

Before I left New York for good, I pulled out my bike and did something I’ve always wanted to do – rode it all the way around the perimeter of Manhattan.

I put together a little page with all the photos I took along with a map of the locations, so rather than repeat myself any further here, if you’re interested, head on over to Bike Around Manhattan.

Manhattan skyline in far distance

Tags: photos, nyc, biking
Categories: Miscellaneous

About me

I'm Kurt, and I make web applications. Want to know more? Check out my about page.

WTF is all this code? I came here for food!

My wife made a new year's resolution to try out at least one new recipe each week. Want to know what she's been feeding me? resolutionfood.blogspot.com