Dynamic Types Make Unit Testing JSON in ASP.NET MVC a Breeze!

by jmorris 18. October 2010 22:57

The new dynamic type in C# 4 was mainly added to offer simpler creation of objects using reflection and the ability to treat objects as they are no matter where they were created: COM interop, DLR, etc. It basically defers static typing until runtime. The object itself is statically typed, however the compiler bypasses compile-time static type checking until runtime.

One place where this kind of late bound typing is really useful is unit testing ASP.NET MVC action methods that return JSON via JsonResult. For example, given the following controller action method:

image 

And the following unit test you’ll quickly discover that while you can see the values as a watch in Visual Studio or while debugging, you cannot actual run an assert on any of the members (Assert.AreEqual(1, data.FeedId) will throw an exception:

image 

It should be relatively obvious as to why this will not work, notably anonymous types are internal to the assembly that they were created in and results.Data returns a System.Object. Using the dynamic keyword, one might assume that the we should be able to run asserts on the properties of the JSON result, but unfortunately, it’s not that simple:

image 

The exception gives some subtle hints as to what the problem is:

'MyFantasyFootBallGuruTests.Controllers.AlertsControllerTests.GetCurrentPick2' failed: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : 'object' does not contain a definition for 'FeedId' at CallSite.Target(Closure , CallSite , Object )  at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0) Controllers\AlertsControllerTests.cs(47,0): at MyFantasyFootBallGuruTests.Controllers.AlertsControllerTests.GetCurrentPick2()

Well it’s somewhat of a hint…the object does not contain a definition for ‘FeedId’ is caused by the fact that while we can see the values with the debugger, the reality is that the ‘object’ is really an anonymous type, which exists in the assembly containing the controller. Since anonymous types by definition are always internal to the assembly they are defined in, the runtime throws an exception. Fortunately, the fix is for this is easy.

When you create a new project (assembly) in Visual Studio, a “Properties” folder with a class called “AssemblyInfo.cs” is automatically created. This class contains attributes that define the metadata of the assembly: the name, description, title, whether or not the assembly is visible to COM components, the version, and other information related to the assembly. There is also another very important attribute to those wishing to test anonymous types in assemblies other than the assembly that the anonymous type is defined in: InternalsVisibleToAttribute.

The InternalsVisibleToAttribute makes types that are normally only visible in the defined assembly to other assemblies specified in the attribute. For instance:

image

Adding this attribute to the assembly that contains the controller classes, makes any anonymous types visible to the unit test assembly, MyFantasyFootballGuruTests. After adding this attribute, the unit tests will not only compile, but allow the properties of the anonymous type to be tested:

image

References

Tags: , , , , , ,

Unit Testing

Scott Guthrie and Leaky Abstractions

by jmorris 27. January 2010 22:02

Scott Guthrie is well known in the .NET world as being the main architect/designer of the ASP.NET framework. He has a very popular blog which is pretty much a press release blog for all Microsofts Web development technologies: ASP.NET, Silverlight, etc. On top of that he is extremely well respected amongst the .NET community and much of what he say's taken to be absolute "word" on best practices and usage of the Microsoft Web technologies.

One thing about his blog, and which I mentioned above, is that it is less of a blog (commentry, opinion, et al) and more of "press release" platform that the commmunity uses to see what's going on with the various Web technologies. Often times his posts are showcases for the various API's that will soon be released and are very tutorial based:

  1. Here is the feature
  2. This is the problem it solves
  3. This is what it does
  4. This is how you do it

Occasionally he'll post work arounds for various issues that developers are facing with technologies, integration or Visual Studio. However, one thing Guthrie rarely does is give an opinion or directly address the community. That is until this recent post in which he discusses the merits of technological debates and his opinion about them. To be honest I agree with him most wholeheartedly about most of his points, but then he begins to speak specifically about ASP.NET Web Forms and ASP.NET MVC debates and again while I follow him for the most part, at one point he really loses me. This assertion in particluar:

"d) I often find debates around programming model appropriateness and abstractions a little silly. Both Web Forms and MVC are programming web framework abstractions, built on top of a broader framework abstraction, programmed with higher level programming languages, running on top of a execution engine abstraction that itself is running on top of a giant abstraction called an OS.  What you are creating with each is HTML/CSS/JavaScript (all abstractions persisted as text, transmitted over HTTP – another higher level protocol abstraction)." 

What he is referring to here, is really the ongoing debate about whether or not ASP.NET WebForms is a "Leaky Abstraction"...here he is trivializing the argument via hasty generalization: "all things software are abstractions, thus all abstractions are good!" This is simply not true. While abstractions are all around us and for the most part are good, many times the abstraction causes more harm than good and MS has a history of creating these type of abstractions and many long-term developers are leery of such solutions.

To be fair, he does qualify his point with the following statement:

"The interesting question to debate is not whether abstractions are good or not – but rather which abstractions feels most natural to you, and which map best to the requirements/scenarios/developers of your project."

However, I feel that he does this not to clarify his point, but to qualify the agenda of the entire post:  WebForms is a good abstraction! However, after working with WebForms since 2002, classic ASP before that, and ASP.NET MVC now, I (and many others) disagree! I think many parts about WebForms are poor abstractions, in fact I am even leery about some of the newer features in ASP.NET MVC 2, but that's another story.

In fact, most of the poor abstractions that exist with WebForms were put there specifically to "shield" developers from the "complexity" of Web development. For example, in the late 90's there were many, many developers who had never developed anything other than desktop apps. To them, learning another technology such as HTML, CSS, or Javascript was a major blocker in moving from desktop to Web development. WebForms gave them what they thought they wanted: a nice abstraction over HTTP and HTML. Instead of hyperlinks, you got buttons. In place of POST and GET you got postbacks and events. This was all nice and good...for awhile.

However, pretty soon the abstraction became a hinderance. SEO became increasingly important and the ugly HTML the WebForms generated became a hinderance and developers had to clear huge hurdles to get the output clean enough to pass an SEO requirement. If it was possible at all. Additionally, the code behind concept created a great place for developers to combine BL, markup (oh, yes), data access, binding, html behavior (javascript),  hackery, etc... into a single co-dependent layer. Seperation of concerns was rarely (from my experiance) practiced as the framework itself lent itself this collusion of sorts.

In the end you get better and better at simply working around the limitations of the abstraction, instead of learning more about what the abstraction is trying simplify. This is bad in so many ways.

A better way to re-phrase Scott's qoute above would be: "The interesting question to debate is not whether abstractions are good or bad, but if the particular abstraction solves the problem is purports to and whether or not it causes more good than bad. If not, it is a poor abstraction." The debate is not about abstractions, it is about specific abstractions that cause developers more grief than good!

 

Tags: , ,

Rendering Views using ASP.NET Webforms and Model View Presenter (MVP) Pattern and AJAX

by jmorris 1. May 2009 21:49

ASP.NET MVC introduces the notion of partial views, which either allow specific Actions to be called on a Controller and the resulting view outputted as HTML or allow Model Data to be passed from the current view to another, child view.

Calling Actions on a Controller and returning “sub” Views is incredible useful in situations were Ajax type behavior is required, since the resulting output is simply raw HTML. The HTML can then be appended to a DOM element via JQuery, some other JavaScript library or simply with straight JavaScript.

Unfortunately if you are still working on Web Forms projects or you have no need or desire to drink the kool-aid of MVC, you are pretty much out of luck for similar functionality built into Web Forms. However, it is fairly easy to implement this sort of behavior within the context of a Web Forms environment and then use a Ajax to render pure HTML from these “partial views.”

The code for doing this is surprising simple and was adapted from a Scott Guthrie posts a few years back:


In this case I allow a Dictionary containing the name value pairs of the properties on the View that will be loaded to be passed in as well. The key must match the name of a Property on the View and if it does the Property is set with the value of the key. This is useful in cases were you would like a parent View to pass data to a child View for initialization situations, etc.

I also have a static collection of Views defined which map a View’s name to a path in my applications root directory. RenderView looks up its path and loads the control before setting the Views data. In my case I load this from a table via a Data Access Object (DAO) in the Global.asax on Application_Start:



The PageUserControlDAO loads the View definitions from the database once when the application is started or the App Pool is restarted/refreshed.

Rendering the View involves calling the RenderView method and passing in the appropriate View name and a Dictionary containing the data to into the view:



In this case I used Page_Load to render the View into a panel (div) which isn’t too exciting. The really useful aspect however is when you combine JQuery and Web Services to render the View on demand from the client.

Rendering Views from the Client Using JQuery and Web Services

The Web Service:



The JQuery code to load the view and attach it to the DOM:


In the JavaScript above, renderView takes three parameters: the name of the View to render, the data to pass to the View, and the DOM container to load the view into. The $.ajax(..) method is a JQuery method that specifies the WebService to use, the method to call (RenderView) and the content type to specify in the request header.

When the method is called like so from the client:

 

renderView('ImageView', { 'CurrentPageElementId': 100 }, $view);


The WebService method is invoked, which renders the view and returns pure HTML that is then appended to the DOM element $view (a simple div or span).

Tags: , , , , , ,

Jeff Morris

Tag cloud

Month List

Page List