Wednesday, January 30, 2008

Testing TempData in ASP.NET MVC

Eventually when testing your controllers you will come across an action that sets TempData.

If you didn’t know, TempData is a session-backed temporary storage dictionary that is available for one single request.  It’s great to pass messages between controllers.

Our Controller classes that we derive from have this as a member property.  However, when testing the controller, this always came up as null.

Reflector is our friend here, so I fired it up and loaded the Controller class.  Then I located the TempData member, and looked at the setter.  It’s marked as internal, so somebody inside this assembly is responsible for creating it.  By using the Reflector Analyze feature, I was able to find exactly where the setter is called.  It’s in the Execute() method.  (this is the general “pipeline” method that all IController implementations must override)

Think about that for a second.  At runtime, the TempData dictionary is set because all requests flow through Execute().  But in my test, I am specifically calling my action method.  There is no Execute() in my test.

To top it off, I can’t set this guy to a new TempDataDictionary because the setter is marked as internal.

Phil Haack tells me they’re working on this issue so we’ll likely see an improvement soon.  In the meantime you can get around the issue by using reflection to set the value.  But first, can we create one?

TempData is stored in session, so it needs a reference to IHttpContext.  Thankfully, we can mock this, however we have to make sure and mock the right parts.

First, create a mock for IHttpContext, create the return values for mocked IHttpRequest & IHttpResponse.  Finally setup return values for IHttpSession as well.  I’ve done all of this in a helper method of my test (though it could be an extention method on the MockRepository ala Phil, but whatever you like).

private IHttpContext GetHttpContext(string requestUrl)
{            
	IHttpRequest request = _mocks.DynamicMock<IHttpRequest>();
	SetupResult.For(request.Url).Return(new Uri(requestUrl));
	IHttpResponse response = _mocks.DynamicMock<IHttpResponse>();
	IHttpSessionState session = _mocks.DynamicMock<IHttpSessionState>();
        IHttpContext httpContext = _mocks.DynamicMock<IHttpContext>();

	SetupResult.For(httpContext.Session).Return(session);
	SetupResult.For(httpContext.Request).Return(request);
	SetupResult.For(httpContext.Response).Return(response);
        _mocks.Replay(request);
        _mocks.Replay(response);
        _mocks.Replay(httpContext);

_tempData = new TempDataDictionary(httpContext);
SetupResult.For(session[null]).IgnoreArguments().Return(_tempData);
_mocks.Replay(session);

 return httpContext; }

This code is a little verbose, but this is something you write once and use in all of your tests. You should notice that the _tempData property is a local field on my test class. I can then take this _tempData variable and inject it (via reflection) onto the controller under test. Here's how:

typeof(FooController).GetProperty("TempData").SetValue(controller, _tempData, null);

And now we can easily test that messages are set in TempData before redirecting or rendering a view.

*update*:  Will Shaver notified me of a typo in the code.  It has been fixed.  Thanks Will!*

Wednesday, January 23, 2008

Interviewing Developers

Part of my job is interviewing developers to assess their technical skills.  The majority of these interviews are at the Junior and Senior levels and I have accumulated quite a bank of questions I like to ask to get to the root of technical problems and see how the candidate responds.

Business_business_suit_237357_l

ASP.NET is a usual topic of discussion because of the vast amount of work that we do and the wide spread adoption of it amongst developers. 

So, let’s say you want to see how much the candidate knows about ViewState.  I start with an example…

Say you have a page with a dropdown on it.  Listed in the dropdown are various types of fruit that come from the database.  To prevent multiple queries for the same data, the code that loads the fruit is inside an if(! IsPostBack) { } block.  With me?

….yes.

So what happens when we click a button and postback?

It is amazing to me to see how many developers differ in their answers just on this alone.  Some people tell me that the values are cleared, some tell me they stay there but they can’t tell me why, and some mention viewstate but they have no idea how it works.

For those who mention ViewState, I inevitably ask, “What happens when we turn it off?”   Of course the values are erased.  “How can we get around that”

Again, many candidates just don’t know what to do in this scenario.  They fail to understand how ASP.NET works on top of HTML, or they have forgotten how the web works, however it may be, those are two very beginner questions, and about 80% of the people that I talk to on the phone struggle there at least some way.

Now granted, some of our candidates are college grads and folks who haven’t done much (or any) .NET.  I don’t hold this against them.

Another area I like to explore is to the various forms of ASP.NET state management (such as cookies, session, cache, application, request) and this filters out another large portion.  Some suggest storing global data (like US States) in a Session variable.  Others can’t tell me how Session works at all.

I find it very difficult to give my recommendation to most of the folks I talk to.  I know there are lots of smart folks out there, and infinitely more not-so-smart ones, but if you’re going to be interviewed by me I will treat it as if you were joining my team.

At the end of my interviews I always ask a question along the lines of “What’s your favorite book?”  to see if they have gotten excited about a programming book (or any book for that matter).  If they say “Teach yourself X in 24 Hours” I will thank them for their time and hang up.

The technical responsibility we have is too great to leave in the hands of those who don’t know what they are doing and refuse to learn.

What about you?  Do you interview other developers?  How do you weed out the cruft and get to the cream?  Is it simply a numbers game?

Thursday, January 17, 2008

The Texas Tour of ASP.NET MVC Comes to a Close

It’s been an exciting two weeks.  I visited user groups in San Antonio, Houston, Austin, and Fort Worth, and I got to meet and connect with a lot of interested developers about the new ASP.NET MVC framework.

Two of the events were recorded, so if I ever get my hands on the recorded bits, I’ll post them here in an easily watchable format.  (Don’t hold your breath though.)

My presentation had a minimal amount of PowerPoint.  I decided to focus on real code.  And people have thanked me for it! 

I covered:

  • Basics of MVC
  • Default Routes
  • Simple Controller / Action
  • Passing data to the views
  • passing strongly typed view data
  • Custom Routes
  • new/edit form for an entity
  • writing tests for controllers
  • rhino mocks for mocking out dependencies
  • dependency injection for controllers (using Windsor)
  • ajax integration with prototype

This is a lot to tackle in my 1/1.5 hour time slot.  And I do get a lot of blank stares when I talk about mock objects and dependency injection, but I think more presentations need to present realistic code, rather than simple examples.  The feedback I’ve gotten about this has been overwhelmingly positive, and I’m really glad people liked it.

Some questions that were asked during my tour…

“Ben, you are phenominally good-looking?  Are you available?”
umm no, I’m married (and now terrified)

What is that cool zoomey tool you used?  That’s awesome!”
that is called ZoomIt, by sysinternals.

What are you using for data access on your entities?”
It’s called Castle ActiveRecord, which uses NHibernate underneath.

Can I use ASP.NET validators?”
—Well not really.  The validators have viewstate, which won’t work.  Your validation definitely belongs in the Model, so you could just do server-side if you want.  If you want clientside validation, you could accomplish a similar result by using marker css classes and some clever javascript  (think <input type=”text” class=”required” name=”address1” /><span class=”error_message”>This is required</span>

If we use this on IIS6, will performance suffer?”
— Probably.  On IIS 5/6 you have to send all requests through ASP.NET, which can be slower.  I’m not an expert in this area, so definitely do your research before making any rash decisions.  When we have Windows Server 2008 and IIS7, expect vast improvements.

Do you know Justice Gray?”
—Sure do.  I’m a bona-fide potential friend of Justice Gray, and even have the certificate to prove it.  It’s serial number marked 00000000000003.  I carry it with me at all times for just such a question.

Can you use co-exist with webforms?”
—Yes!  If you hit a page with the .aspx extension, the PageHandlerFactory will pick it up and you will be in WebForms Land.  If you instead hit a route, you’ll be in MVC Land.  Learn to know the difference and you’ll be fine.

Isn’t it dangerous to output strings directly like that?”
—Yes it is.  Read my post about html encoding your values.

Your hair is impeccable?  What kind of gel do you use?”
— It’s called Fructis something-or-other… and it’s awesome!

So Microsoft has two methods of developing web applications?  Which should I choose?”
—If you like the rich eventing model and the ability to save state and mimick a smart client ui, then choose web forms.  If you value clean html, urls, separation of concerns, and testability, then choose MVC.  I will be choosing MVC more often than not from here on out.

When will it be released”
—Gawsh, I don’t know?  Fall 2008?  As soon as I know I’ll post it here.

(admittedly, a couple of those questions were not asked — I’ll let you guess which ones)

You can download the code and the presentation here:

File Attachment: save the world with asp.net mvc.zip (1612 KB)

I’d like to thank the user group leaders for having me speak, it was certainly a pleasure.  Where will the next tour be?

Wednesday, January 16, 2008

Thank you ADNUG and FWDNUG

I got the chance to meet an enthusiastic bunch of folks in Austin and Fort Worth this week, and I wrapped up my Texas Tour of MVC.  I really want to say thanks to groups for having me.  It was a pleasure to speak and connect with fellow developers in Texas.

I’ll be posting a massive recap this week that includes the code and powerpoint that I delivered.  I’d appreciate any and all feedback.

Now for that long drive home…

Saturday, January 12, 2008

Visual Studio 2008 CSS Support - Not Quite

One of the often-touted new features of VS 2008 is the improved CSS support.

I like having intellisense for CSS, sure, but I dont’ want to have a warning for classes that don’t exist…. like this:

Vs2008-css-warning

That green squiggly indicates a compiler warning.  It can’t find the CSS class, (which is referenced in the Master Page). 

But there are other reasons why you might want to define a class without defining an associated style.  You might be using it to distinctly select elements from the DOM using javascript. 

The ever-so-awesome prototype framework introduced this syntax:

$$(‘.info’)

which would select all of the elements with a class name of “info” for you to work with.

Just about every other javascript library out there now supports this syntax (or a similar one).

If this bugs you, you can turn it off by checking this box (in Tools -> Options) :

Vs2008-turn-off-html-errors

You may not want to do this, though…  it could potentially save you time if you’re looking for a rendering bug.

Another part of VS 2008 that I don’t really care about is this CSS designer.  I can’t imagine anyone who would actually use this.

I mean, come on… look at it!

Vs2008-css-builder

I guess if you don’t know CSS very well, you might want some options.  But that form is more confusing to me than border-top: solid 1px #999;.

(and one could argue, if you don’t know CSS, should you be defining styles at all?)

I really applaud Microsoft’s attempt to bring a better CSS development experience to the masses, but I think they missed the mark on this one.

Thursday, January 10, 2008

Thank you HDNUG!

I enjoyed giving the presentation on ASP.NET MVC tonight to about 90 eager developers at HDNUG here in Houston.

There were a few people that had played with the framework before, a lot who had heard of it, and about 1/3 of the room had never heard of it.  Awesome!

There’s always a balance between how intro a talk should be, but one of my goals with this talk is to show real application code; to show how you actually test these things, and what types of practices and tools that can enable this and make it easy.

I hope that the talk was well received.  If you went, I’d love to hear your feedback in the comments!

Some links from the talk:

I’m sending the code over to be posted at HDNUG right now.  After my tour ends next week, I’ll post a large recap that includes code and hopefully answers to common questions that I’ve been hearing.

They also recorded the talk, so once I get my hands on the video, I’ll throw it up here so others can have a look.

Thanks for having me HDNUG!

The Über USB Cable

While shopping for a presentation clicker at Best Buy, I ran across this little gem.

It’s a flippin’ USB cable for $41.99!  It’s labeled as a “Microsoft Vista Migration Cable.”

IMAGE_027

IMAGE_028

Too bad it wasn’t gold plated, otherwise I would have jumped all over it.

Wednesday, January 09, 2008

Be careful outputting strings in ASP.NET MVC

During my presentation at Alamo Coders last night, someon mentioned that it is unsafe to output user-entered strings like this:

<h2><%= college.Name %></h2>

The reason is, of course, that the user could be malicious and enter in a string such as this:

“<script>alert(‘I am evil’);</script>”

And it would evaluated on the page and all of your users would get an alert box.  This is leaving your door wide-open to clever attacks known as Cross Site Scripting and is very dangerous.

Instead, we should escape these strings so that they aren’t rendered as HTML or javascript, but rather textual characters.  That means that < will be translated to &lt; and so on.

To do that, the Html helpers that ship with the framework give you an Encode method, letting you do something like:

<h2><%= Html.Encode(college.Name) %></h2>

But the syntax is a bit cumbersome for every outputted value on a page.  I prefer the way Rails handles it… like this:

<h2><%= h(college.Name) %></h2>

And it turns out that you can add this extension method somewhere and be done with it:

public static string h(this ViewPage page, string input)
{
     return new HtmlHelper(page.ViewContext).Encode(input);
}
And that’s it!  Just remember to take this precaution, or you’ll regret it later.

Thank you Alamo Coders .NET!

Last night I kicked off my Texas Tour of MVC at Alamo Coders in San Antonio.

The room was pretty small and they filled it up with about 25 people.  It was a bit more personal and cozy than the Houston .NET User’s Group that I’m used to.

I ran a bit short on time, but luckily I had my ready-baked turkey in another folder so I was able to show my ajax portion of the presentation and I think it went well.

I got some feedback from a few people who found the talk to be covering too much.  (In addition to ASP.NET MVC, I covered inversion of control, mock objects, and a few other things).  I wish I had a bit more time to explain these things in more detail, as it can be like drinking from the firehose, however I think they are important topics, and necessary to understand if you expect to properly unit testing on your controllers.

For those of you that were there, here are the relevant links for more information…

Inversion of Control:

Mock Objects:

The javascript library I was using was prototype, available here: http://www.prototypejs.org.

Thanks again to Alamo Coders for having me!

Sunday, December 30, 2007

ASP.NET MVC Tour of Texas

Want to see what the hype is all about with the new ASP.NET MVC Framework?

I’ll be touring Texas speaking about it.  If you live in Texas, come check out my talk “ASP.NET MVC – Save the Developer, Save the World.”

Here’s the confirmed schedule:

  • January 8th – Alamo Coders (San Antonio)
  • January 10th – HDNUG (Houston)
  • January 14th – ADNUG (Austin)
  • January 15th – FWDNUG (Fort Worth)

We’ll take a look at the new framework, the design goals, and dig into some code.

Hope to see you there!

 

Credit - Refinance - Personal Loan - Internet Marketing