Site Meter
 
 

Using the ASP.NET MVC source code to debug your app

Most ASP.NET MVC developers know that the framework source code is available. This means you can:

  • Read the source code to see how things work
  • Edit, compile, and use your own custom build with your own modifications (though this is almost certainly not necessary, as the framework gives you plenty of extensibility options)

Instead of just reading the MVC Framework source code in the abstract, one of the best ways of understanding what’s going on is to put it directly into your application’s solution. You can include the System.Web.Mvc C# project in your solution (as if you created it!), and then handily step into and out of its code while debugging, or use Visual Studio’s Go to Declaration command (or ReSharper’s) to navigate from your framework class references directly into the source. Personally, I find this very useful.

Attaching the System.Web.Mvc source code to your solution

Here’s how to include the System.Web.Mvc project source in your solution:

  1. Download the ASP.NET MVC source code from CodePlex (be sure to get the version that corresponds to whatever version of ASP.NET MVC your app already uses). Extract the ZIP file to some convenient location.
  2. Add System.Web.Mvc as an existing project. In Visual Studio, open your existing application, then go to File –> Add –> Existing Project. Find and select System.Web.Mvc.csproj, which will be in the source code you just extracted from the ZIP file, probably in the MVC\src\SystemWebMvc subdirectory. You’ll now have System.Web.Mvc in Solution Explorer:
    image
  3. Remove your app’s existing reference to System.Web.Mvc. Just find it in the list of references, right-click it, and choose Remove.
    image 
    This eliminates the reference to the GAC version of System.Web.Mvc (the one that was registered when you first installed ASP.NET MVC).
  4. Add a project reference to the source code version of System.Web.Mvc. Right-click on your app in Solution Explorer, choose Add Reference, go to the Projects tab, and select System.Web.Mvc.
    image 

That’s it! You can now compile and run your application, and you’ll have a live reference to the framework source code, so you can step in and out of it, and can jump directly from any reference in your own source code to the corresponding point in the System.Web.Mvc source code. This can make debugging much easier.

Stop being so ambiguous!

Actually, there is a bit of a snag. If you have view pages without code-behind files (which is the default, since the Release Candidate), then when you try to run your app, you’ll get the following error:

image

You’ve now got one self-compiled instance of System.Web.Mvc.dll in your application’s \bin folder, plus the official original copy in your GAC from when you first installed ASP.NET MVC. So how is the framework supposed to decide which one to use?

Well, the only reason it considers the GAC version is that your web.config file tells it to. Go and edit your web.config file and comment out the System.Web.Mvc GAC-version reference:

image

Now it will only consider the version in your \bin folder, so the ambiguity ("Parser Error”) will go away.

Update: Wait, there’s more! Another config change you need to make – if you want to run a custom build of ASP.NET MVC – is in /Views/web.config (note: that’s not your top-level web.config). Since the RC, strongly-typed views depend on a clever page parser filter. Find this string:

pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"

… and change it to:

pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

That just tells the page compiler that it can use your custom build of ViewTypeParserFilter (and that it doesn’t have to use the GAC version). If you don’t, then strongly-typed views will throw the error “‘object’ does not contain a definition for ‘YourModelType‘”.

What about deployment?

When you come to deploy your app to another server, remember that your web.config file now doesn’t reference the GAC version of System.Web.Mvc, and the rest of your code is compiled against your custom build. To make it work on another server, you can either:

  • Deploy your custom build of ASP.NET MVC in the \bin folder. Your custom build of the assembly will already be in your \bin folder, so this is what will happen automatically.
  • Reverse the steps you just took above (which means manually editing your app’s .csproj file to reintroduce a reference to the GAC version of System.Web.Mvc, rather than the project reference). You could probably make this part of your automated build process.

I have found this technique extremely useful when trying to understand what the MVC Framework is actually doing with my application.

25 Responses to Using the ASP.NET MVC source code to debug your app

  1. Ray

    What do you think of just having the .pdb file of the mvc lib instead of including the actual source project of it for debugging? That way you can still debug into the source and you don’t have to include another lib in your solution.

  2. Nice post, Will try this out

  3. I tried this and it is working fine for pages that don’t use strongly typed views. But I created a strongly typed view and it is telling me the following:

    CS1061: ‘object’ does not contain a definition for ‘FooDogInt’ and no extension method ‘FooDogInt’ accepting a first argument of type ‘object’ could be found (are you missing a using directive or an assembly reference?)

    So it is apparently trying to treat the model as an instance of Object…though it obviously isn’t. Did you not run into this?

  4. Steve

    @Eric – aha, thanks for pointing that out! That’s a new behaviour in the RC that sneaked past me.

    I’ve updated this blog post (see the “Update: Wait, there’s more!” segment above), explaining another config tweak that’s now required.

  5. Pingback: Debugging with MVC Source « PrimeDigit - A Design Blog by Will Shaver

  6. stunt

    Hi! dude
    good application.

  7. This can also occur if you add a standard master page and then attempt to switch the inherits tag to “System.Web.MVC.ViewMasterPage” after it created the code behind files for the standard master page (even if you remove the codebehind tag). I ended up deleting the code behind and designer files, then recompile and everyting works.

    Interesting info tho.

  8. I am new to MVC and learning it from different website thanks

  9. Thank you for this tip. Very helpful!

  10. Jon

    Any idea why this is not working? I can’t compile my app (it has multiple projects – is this a problem?). I’m getting “The type ‘System.Web.Mvc.Controller’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′.

  11. Andy

    Very useful, Steve! (As is your book.)

    Anyone been successful getting MVC 1.0 source debugging to work in VS 2010 on .NET 4 target? I tried and am getting security rule exceptions on GetObjectData() even though my controllers don’t implement GetObjectData() (just use base Controller implementation). Perhaps subtle differences between .NET 3.5 and 4 security causing these problems?

    -Andy

    P.S. Similar security rule issues reported on this string http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=464751

    System.TypeLoadException was unhandled by user code
    Message=Inheritance security rules violated while overriding member: ‘System.Web.Mvc.TempDataDictionary.System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)’. Security accessibility of the overriding method must match the security accessibility of the method being overriden.
    Source=System.Web.Mvc
    TypeName=System.Web.Mvc.TempDataDictionary.System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)
    StackTrace:
    at System.Web.Mvc.Controller.ExecuteCore()
    at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) in C:\mydocs\Visual Studio 10\Projects\GroupDat\Source\SystemWebMvc-10Src\Mvc\ControllerBase.cs:line 76
    at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) in C:\mydocs\Visual Studio 10\Projects\GroupDat\Source\SystemWebMvc-10Src\Mvc\ControllerBase.cs:line 87
    at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) in C:\mydocs\Visual Studio 10\Projects\GroupDat\Source\SystemWebMvc-10Src\Mvc\MvcHandler.cs:line 89
    at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) in C:\mydocs\Visual Studio 10\Projects\GroupDat\Source\SystemWebMvc-10Src\Mvc\MvcHandler.cs:line 68
    at System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) in C:\mydocs\Visual Studio 10\Projects\GroupDat\Source\SystemWebMvc-10Src\Mvc\MvcHandler.cs:line 104
    at System.Web.Mvc.MvcHttpHandler.VerifyAndProcessRequest(IHttpHandler httpHandler, HttpContextBase httpContext) in C:\mydocs\Visual Studio 10\Projects\GroupDat\Source\SystemWebMvc-10Src\Mvc\MvcHttpHandler.cs:line 12
    at System.Web.Routing.UrlRoutingHandler.ProcessRequest(HttpContextBase httpContext)
    at System.Web.Routing.UrlRoutingHandler.ProcessRequest(HttpContext httpContext)
    at System.Web.Routing.UrlRoutingHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext context)
    at MvcApp._Default.Page_Load(Object sender, EventArgs e) in C:\mydocs\Visual Studio 10\Projects\GroupDat\Source\MvcApp\Default.aspx.cs:line 18
    at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
    at System.Web.UI.Control.OnLoad(EventArgs e)
    at System.Web.UI.Control.LoadRecursive()
    at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
    InnerException:

  12. Pingback: Servefault.com

  13. Roma

    Nice post!
    It’s working perfectly event with MVC2-preview1-sourceCode!
    Reshaper pointed me to 2 more web.config keys that need to be set to null.

    pageBaseType=”System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null”

    userControlBaseType=”System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null”>

  14. Pingback: Kristof's Blog :: ASP.NET MVC Model binding to a list.

  15. Paul Spencer

    Many Thanks! been trying to figure out what part of the MVC magic I was doing wrong, banging head against desk for hours. This is now letting my find what I’ve done wrong, instead of trying to guess!

  16. Hi Steve,

    Can this be done even in projects that reference other third party assemblies (say, Telerik.Web.Mvc) which in turn reference MVC2?

    I’ve done the setup according to your instructions, but when I try to compile I get compilation errors like:

    “Error 49 The type ‘System.Web.Mvc.IActionFilter’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′.”

    It seems like my third party assemblies aren’t aware of the System.Web.Mvc project? Or is the problem that they rely on a specific PublicKeyToken?

  17. Very nice article. You are right, doing it this way helps developers understand MVC better.

    Arun

  18. Pingback: ASP.NET MVC 2 throws exception for ‘favicon.ico’ - IBloggable - implemented

  19. Parker

    Hi Steve,
    It’s a nice way.
    A question is I’m trying to debug the mvc source code with this way.
    But when it steps to ControllerActionInvoker.InvokeAction(..) and throws an exception on “InvokeActionResult(controllerContext, exceptionContext.Result);” which is “error CS0012: The type ‘System.Web.Mvc.HtmlHelper’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′.”

    I work in vs2010 asp.net mvc2 , and could you help me?
    Thank you very much for any suggestion.

  20. Pingback: Debugging von ASP.NET-MVC2-Applikationen « Das Megos .NET-Weblog

  21. база авто

  22. Really helpful, thanks a lot

  23. Dani

    Nice tutorial, but with the razor view engine it will not work…

  24. Good article buddy. I think it’s not a bad idea if you tell us how can we “get sure that the ASP.NET MVC version is the same as the version we’re using”. Also I think if we use a newer version, since the source code is not in our solution, no problem should arise.