Scott Hanselman

ASP.NET MVC Beta and RC Upgrades - Confirm your Expectations and Version Numbers in Production Environments

May 22, '12 Comments [18] Posted in ASP.NET | ASP.NET MVC
Sponsored By

I was working on an app locally using a daily build (newer than the currently released one) of ASP.NET MVC and deployed it to a host. I noticed this weird CSS issue. See how the text box on the left running on localhost is small and not styled while the one on the right running on the host is the correct width? You can click on the screenshot if you need to see more.

The Local website's textbox is poorly styled while the same app running the host has a correctly-styled textbox

I dug around a little and using the F12 browser developer tools (as well as good old View Source) I noticed the HTML being created was different! My local app was producing one bit of markup, then when I deployed the same app to my host I would get different markup!

Here's the app's markup running locally:

<input class="text-box single-line" data-val="true" 
data-val-date="The field EventDate must be a date."
data-val-required="The EventDate field is required."
id="EventDate" name="EventDate" type="datetime" value="5/29/2012 1:48:23 AM" />

Here's while running on the host:

<input class="text-box single-line" data-val="true" 
data-val-date="The field EventDate must be a date."
data-val-required="The EventDate field is required."
id="EventDate" name="EventDate" type="text" value="5/29/2012 1:48:23 AM" />

I realize I could have made it more obvious for this but I wanted to make the point that it took a second to notice that my standard ASP.NET MVC Helper call...

<div class="editor-field">
@Html.EditorFor(model => model.EventDate)
@Html.ValidationMessageFor(model => model.EventDate)
</div>

...was returning type="text" on the host but type="datetime" on my local machine and that difference was picked up CSS that targeted specific input tags. Weird. Now, EditorFor() can have its behavior overridden with custom files in ~\Shared\EditorTemplates so if there was a DateTime.cshtml in there that would make sense. There wasn't. I wasn't using the very lovely MvcHtml5Templates NuGet package by Scott Kirkland, so that wasn't it.

My spider-sense was telling me this must be a versioning issue but everything looked right. My only explanation was that somehow what was running on the host was different from what was running on my local machine.

I asked around work and Eilon Lipton suggested I run this snippet to check the version of ASP.NET MVC. He's basically saying "Hey, where did this well known type come from?"

public ActionResult ShowVersion()
{
Type t = null;
try
{
t = Type.GetType("System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35");
}
catch (Exception e)
{
Response.Write("Error finding MVC: " + e.ToString());

}
if (t == null)
{
Response.Write("Can't find MVC");
}
else
{
Response.Write("Found MVC at " + t.Assembly.CodeBase + ", IsInGac = " + t.Assembly.GlobalAssemblyCache + "<br>");
var verAttr = t.Assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyFileVersionAttribute), true)[0] as System.Reflection.AssemblyFileVersionAttribute;
Response.Write("Version = " + verAttr.Version + "<br>");

}
return null;
}

Even better, rather than using this code, I can use the MvcDiagnostics NuGet Package and get THIS useful data from Brad Wilson. Hopefully he will update it for ASP.NET MVC 4 although it worked well.

MvcDiagnostics NuGet Package

This package gives you lots of useful information for debugging weird situations.

ASP.NET MVC Diagnostics Utility gives lots of useful data

Anyway, I put the diagnostic code in a controller and ran it and got this (this version is faked):

Found MVC at file:///C:/mysite/bin/System.Web.Mvc.DLL, IsInGac = False
Version = 4.0.77777.0

Hang on, but my local result was this:

Found MVC at file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Web.Mvc/v4.0_4.0.0.0__31bf3856ad364e35/System.Web.Mvc.dll, IsInGac = True
Version = 4.0.99999.0

My local version was newer and was running from the GAC (Global Assembly Cache) but the hosted version was older and running locally. That means I had older ASP.NET MVC files floating around that my project referenced and deployed to the host.

Aside: The specific change that "got" me here was actually the first external contribution accepted to ASP.NET MVC. It's the one that Miguel de Icaza sent a pull request for while I was on stage at DevConnections. The change is to output HTML5 input types for common default data types, like <input type="datetime"> for System.DateTime when using EditorFor().

It took me a moment to remember that I hadn't added the reference to ASP.NET MVC manually but rather via the NuGet Package Manager. This became crystal clear when I used the built-in NuGet Package Visualizer (from Tools | Library Package Manager) to see the package dependency chain:

The ASP.NET NuGet Packages as viewed in a directed graph in the NuGet Package Visualizer

Basically I needed to either update my out of date NuGet packages or add the assembly references manually without NuGet.

Since I was working on a daily build I did it manually. When you update your ASP.NET MVC 4 Beta applications to a newer build (like ASP.NET MVC 4 Release Candidate (whenever that comes out) or the final Release) you'll want to do update all your packages via NuGet and confirm you're getting the versions and behavior you expect. The NuGet Package Visualizer is a hidden gem indeed.

So, a general reminder to folks (and a specific lesson when upgrading between ASP.NET MVC builds):

  • know your version numbers, what you want, what you're referencing.
  • confirm your version numbers in your debug and production environment.
    • Perhaps a health-check page or a runnable Integration Test to assert your assumptions
  • update your NuGet packages keep your references, and thus your ~\bin up to date
  • know where your assemblies are being loaded from (the GAC or locally)

Hope this helps!


Sponsor: I want to thank my friends at DevExpress for sponsoring this week's feed. Take a moment and check out their stuff! Touch-enabled apps require developers to re-think design & user experiences. DevExpress tools help you take on these new challenges using your existing skills & today’s technologies.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Tuesday, May 22, 2012 10:56:23 AM UTC
You're ASP.NETs Mark Russinovich !
Tuesday, May 22, 2012 11:40:00 AM UTC
Whilst an interesting article 2 things did stick out for me:

1. You use IE to debug web applications?!
2. When .Net was first released everyone was touting 'no more DLL hell', what you didn't tell us was that it would now be called 'Assembly hell'.

:-)
Tuesday, May 22, 2012 12:22:58 PM UTC
The NuGet Package Visualizer is a hidden gem indeed.

No as useful as it can be:
This feature takes advantage of the DGML support in Visual Studio. Creating the visualization is only supported in Visual Studio Ultimate. Viewing a DGML diagram is only supported in Visual Studio Premium or Higher.

Tuesday, May 22, 2012 3:12:45 PM UTC
Good detective work, but kind of ridiculous that we have to understand such details (isn't this just a variation on DLL hell?).
Mike
Tuesday, May 22, 2012 6:39:39 PM UTC
Hi Scott.

I'm trying to send all fields from a cshtml to the controller method (Edit) to save all fields that I have on a edit page.

For example:

I have a method:
public ActionResult Edit(companiaentities ciaentity)
{
code here to send that ciaentity that should receive from cshtml to send to another class to update compania.

}

but I don't know how.

can you help me on this please?

Thanks a lot.
Frederic Alvarez
Wednesday, May 23, 2012 1:35:31 AM UTC
@Fredric,

That binding should happen automatically if the view page is referencing that entity. What kind of trouble are you having?

If you are having trouble getting started why not check out some of the MVC3 Tutorials?
Wednesday, May 23, 2012 11:50:17 AM UTC
So excited about NuGet Package Visualizer, so sad it's not available for Pro version.

Anyone know of a DGML -> GraphViz bit?

Might not be too hard to write one...
Wednesday, May 23, 2012 5:51:24 PM UTC
So, all along we've been told over and over again from MS that we shouldn't really worry about .NET 4.5 having the same version (deployed) as .NET 4.0. Yet, here's a perfect example of a VERY simple issue or problem that resulted from both of these versions masquerading around as the same issue.

Scott, you're obviously sharp and you were able to quickly sort through this. Imagine some poor schmoe working in IT somewhere who runs into something similar - but who isn't a developer and can't figure this out. Something like this is and will be the perfect example of how end-users in the 'trenches' will end up with a VERY sour taste in their mouths against how MS is handling versioning.

And... I'll say it again: it's fine to include bug-fixes into the in-place replacement for .NET 4.5. But once you start adding new features (async, datetime editors, and other APIs) then pretending that these highly distinct versions of the .NET Framework are both the same or equal is just silly.

And, sadly, it kind of makes your general reminders almost moot - as your first reminder is to 'know' your version numbers. Only, we can't - because the CLR team has decided that two distinct versions of the framework are allowed to masquerade around as the same version of the framework.

And if it sounds like i'm cranky, well, i am. Because no one would try to allow two totally different sets of APIs to pass themselves off as the same version of something. It completely violates the basic purpose and intent of even having versions.

And, long story short, i'm sure we'll get fairly used to being 'burned' by crap like this that takes tons of time to sort out.

--Mike
Wednesday, May 23, 2012 5:52:19 PM UTC
Hi James.

Thanks a lot for answer me.

My problem is that I'm not working with SQL server, so I must have a classes to implement update, create, delete and so on.

I have to method for edit:

1.- public ActionResult Edit(string strCodigo)
{
this method works very well
}

[HTTPPOST]
2.- public ActionResult Edit(classEntities ciaEntity)
{
here is the problem, I don't know tell to the cshtml that send here the entity.
}

I thought that I could tell in the cshtml the follow:

@html.ActionLink("Edit", "Edit", here the @Model, to send back to the controller the data that I modify to update it.


Thanks.
Frederic Alvarez
Thursday, May 24, 2012 2:21:38 AM UTC
@Frederic Alvarez

Don't use Scotts blog post on DLL diagnostics as a discussion forum for a razor template's issue, try stack overflow!!

@Scott, helpful post - a classic "works on my machine" scenario!
Thursday, May 24, 2012 6:44:13 AM UTC
@Scott, helpful post if I ever get the same problem. :)
Sunday, May 27, 2012 5:24:12 AM UTC
i hace this problem with your neew site that I can not read it properly on my Nokia E5-00 with an Opera mini browser. Whenever you have inserted a code snippet, it is un readable for me.

Hope to see better results in the future.

P. S. I cudn't find a place to put my feedback so putting it here in comments section.
Naveed Butt
Tuesday, May 29, 2012 7:52:00 AM UTC
superb feature
Wednesday, May 30, 2012 11:13:44 PM UTC
What are f12 developer tools???
Please stop promoting that horrible browser!!!

https://www.google.com/chrome
Hmmm
Thursday, May 31, 2012 5:11:08 AM UTC
I never heard about Mvc.Diagnostics before, but it looks like a good feature. Thanks for sharing!
Thursday, May 31, 2012 2:15:41 PM UTC
@Scott This's great post.
Thursday, June 07, 2012 7:16:38 PM UTC
"My local version was newer and was running from the GAC" - same here, but the ShowVersion check failed because it didn't find the dll in the bin, and I guess that exception prevented it from continuing and looking in the GAC. I had to set Copy Local = true in the reference properties and rebuild.

@Naveed: I love Opera Mini (85% less data usage!), but it's not a browser in the traditional sense - content is rendered on a proxy server. With no rendering engine on the device, it will always have problems with some things, especially on-the-fly DOM manipulation. Not sure what the problem is with the snippets (maybe Mini can't handle overflow:auto), but they do appear in Opera Mobile.
Takk
Friday, August 10, 2012 1:16:01 AM UTC
@Michael - while I agree on the framework CLR point you're making I don't think this has anything to do with Scott's issue. I ran into the same thing several times, everytime I installed a new release build after running on the nightly builds for a while.

I think the bigger problem here is NuGet, or rather how NuGet handles updates. The only way to really force updates on NuGet is to remove the packages and re-add them or - as I did - create a new project and copy the new package reference version numbers and then kill the package folder.

But as you say somebody not that familiar with NuGet and how it works will never discover that. It's a pain in the ass.

NuGet needs an easier mechanism to easily see what version you're running and what version is available. Visual Studio should also provide some sort of indicator where an assembly is coming from. Managing NuGet assemblies across multiple projects that use the same packages too is painful. Really hard to see what's going where.
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.