If you are working through the tutorial from the beginning, you can read starting with the earliest posts first.


Comments off:

Posted in Uncategorized on June 18th, 2011 by matt – Comments Off

The spam to content ratio in the comments currently exceeds 99 to 1. I’ve turned comments off, at least for now.

If you’d like to contact me, send me an email (@ domain name, my name is “matt”).

An alternate tutorial for ASP.NET MVC:

Posted in Uncategorized on March 11th, 2011 by matt – Comments Off

Although there’s still a lot of people who end up learning .NET MVC with NerdDinner, if you’re a newcomer to .NET MVC, I’d honestly recommend a different starting place:

ASP.NET MVC Music Store

The Music Store is a newer, and shorter, intro to MVC concepts. It’s all available online like NerdDinner, starting simply and building up to a functional demo application. I think it’s better than NerdDinner because:

  • You’re working with newer, nicer tools instead of outdated kit that you probably won’t ever see in production. You get to try out Razor (admittedly you might have to do .aspx in production sometime). You’re using the new and (genuinely) improved MVC 3 methods. The scaffolding (which you use a lot in both tutorials) is greatly improved in VS 2010. You’re working with Entity Framework rather than the semi-deprecated LINQ To SQL.
  • It must be said–the Music Store has many, many fewer bugs and glitches. There are a few errors and confusing areas (especially toward the end), but only a few, and typically not very serious or difficult to sort out. Also, there are user comments under each section, which are sometimes helpful if you do encounter something strange.
There a couple of  minuses compared to NerdDinner:
  • The thinking behind the shopping cart and placing orders for albums is a bit odd and, to me at least, was not easy to understand and follow.
  • There’s not as much content. Each section is shorter and there’s less detail. There is no section on unit testing.
Also, the Music Store walkthrough assumes a somewhat higher level of comfort with Visual Studio and computer skills generally. There’s an expectation that the reader can unpack and accomplish basic tasks without hand holding. Most readers will probably appreciate this, but beginners might get stuck at some of the condensed places.

NerdDinner Part 12 Discussion and Source Code

Posted in Uncategorized on January 12th, 2011 by matt – Comments Off

This post is a discussion of Part 12 of the online NerdDinner ASP.NET MVC tutorial.

Here we get an intro to unit testing and some related concepts like dependency injection. This is another long one–if you’re new to these ideas, expect to spend some time here.

Unit testing seems to be one of those things that everyone knows they should do, they make an occasional effort toward doing, but thorough testing often ends up postponed forever until later when they’re not so busy. That said, it’s a discipline I’d like to use more of, and it’s one you want to at least have passing familiarity with.

So let’s get started. Getting DinnerTest.cs set up should be easy–just be sure to put it under a new \Models folder. Go ahead and run those tests–you should get two green checkmarks. There’s something that appeals to my monkey brain about seeing those green checkmarks, it’s like playing a game.

(By the way, I think the Visual Studio configuration recommendations are good. I applied them myself.)

Now we start creating a new test. This one will be trickier. Be careful when adding the new unit test to \Controllers. You want to click on the Controllers folder and Add -> “New Test”. Don’t do what I did and choose Add -> “Unit Test”, that road will give you more than you want to take on right now.

To get the new unit test to work, you’ll have to add some namespace references. You’re used to this by now. Add using NerdDinner.Controllers; and using System.Web.Mvc; to your list at the top of the file. Run the test and see the red Xs pop up–we’re throwing exceptions. We don’t have a db object–and it would be kind of a mess to make a real one for testing.

Enter dependency injection. Instead of always creating our db inside the class, we’ll alter our constructors to allow us to pass a “db” object in from outside. In our tests here, this will be a fake db object instead of a real one.

There’s another step. We want our controller to work with the fake db object as well as the real one. But the fake db and the real db will have two different object types. So, we’ll add an interface layer that will be compatible with both at once. (You’ve probably worked with interfaces before, but if you’re not used to writing them, you may want to google (er, Bing!) something like “csharp learn interfaces” to get an overview.)

The next step in the tutorial is creating this interface layer. It starts off a little confusing: don’t add the interface manually, do use the refactoring tools. However, there’s one tweak you’ll want to make. The autogenerated code shows:

interface IDinnerRepository

but you’ll want to change it to:

public interface IDinnerRepository

Fix up the constructors for DinnersController.cs as shown. The new parameterized constructor will let us pass in our fake db for testing. (Trouble finding DinnerRepository.cs and DinnersController.cs? The changes we’re making are in the actual web project, not in the testing project. Use the real project from Parts 1 – 11.)

Add the FakeDinnerRepository class (we’re back to the testing project again). Note that you need to add using NerdDinner.Models; at the top of the class, and you have to start the implementation (i.e., type ” : IDinnerRepository ” yourself) before the right click “Implement Interface” becomes available. Generate the stubs, then copy the code from the next part of the tutorial and finish setting up the fake class with real methods. (Sure, you can skip generating the stubs and go straight to the real code if that is clear to you.)

Now we can close the circle and come back to DinnersControllerTest, and put in new tests (with the same names) that use FakeDinnerRepository to interact with the controller in our web project. We get real, passing test results. Hurray! (Note that I had to add using NerdDinner.Models; and using NerdDinner.Tests.Fakes; to the test class to get it to compile.) The new tests themselves are simple–most of the new code is about setting up the new FakeDinnerRepository.

We then set up another testing method (we’re not changing the actual controller, don’t be confused by the controller text) to test Edit-GET. It fails. We don’t have a User object. Our solution here is a little different than before. We won’t try to inject a fake User via the constructor this time. Instead, we’ll use a mocking framework to create a fake User, and after creating the controller in our test environment, we’ll overwrite the default (null) User with this fake User.

The tutorial uses Moq as a mocking framework. The link they give for downloading Moq is dead, but you can still get it here: http://code.google.com/p/moq/. (Moq is highly regarded as a mocking framework, FWIW. Search for discussions of mocking frameworks on, say, StackOverflow, and you’ll see a lot of people choose it as their top pick.) You’ll be downloading a newer version than the one in the tutorial, that’s OK, they’re compatible. Put the binaries somewhere you like and add a reference to Moq.dll to your NerdDinner.Tests project.

Now you can add the new CreateDinnersControllerAs() method. (You’ll need to add using Moq; to your using directives to get it to compile.) Isn’t it handy to have a ControllerContext that you can overwrite so easily?  :)

Add the two new Edit testing methods from the tutorial, one expecting a typed view of type DinnerModel, the other expecting the InvalidOwner view. Notice our ValidOwner test uses “SomeUser” as the user name–matching the user name we set up when creating the FakeDinnerRepository. You’ll also want to delete the old EditAction_Should_Return_View_For_ValidDinner() method–don’t try to fix it up, just scrap it. Run the tests and both the new tests should both pass. (The method names are a little different in the tutorial’s screenshot of the test run–disregard that screenshot.)

For the last bit of Part 12 (and the end of the online tutorial), we add two more methods that simulate saving with and without errors. (Again, we aren’t changing the controller, only the testing code.) You’ll notice we don’t have to say anything special in our test to hit Edit-POST, we just pass the correct parameters to hit that overload.

Thinking about what’s happening here might get a little confusing. Remember that our test suite is always creating a controller using CreateDinnerController(). That creates a real controller using a FakeDinnerRepository, which has a fake Save() method. The controller doesn’t “know” it’s using a fake .Save() on a fake repository–but for these tests, it doesn’t need to. (We could set up more tests in the data layer if we wanted to check the internals of .Save() as well.)

. . . and that’s the end. It was fun–I hope you thought so too. Despite the many little glitches, I think NerdDinner is an excellent way to get started learning ASP.NET MVC. It’s much more comprehensive and “serious” than you normally get in an intro-to-X tutorial.

Feel free to drop me a note if you’ve got any questions (or notice any little mistakes!) about this blog.

So long!

You can download my source code for NerdDinner Part 12 here.

NerdDinner Part 11 Discussion and Source Code

Posted in Uncategorized on January 6th, 2011 by matt – 1 Comment

This post is a discussion of Part 11 of the online NerdDinner ASP.NET MVC tutorial.

In part 11, we add support for a visual map display using AJAX. (This is a long one.)

Create Map.ascx, filling in the details, and then create Map.js (a busy little guy). Add the new code to DinnerForm.ascx. Be careful with the tutorial code here–the authors cut some code for brevity and IMO it’s a little confusing. Don’t just overwrite your code willy-nilly–alter carefully: 1) wrap the existing HTML form fields in <div id=”dinnerDiv”>, 2) add the new <div id=”mapDiv”> with the RenderPartial(), and 3) add the new javascript block with the $(document).ready() function setup.

We’re ready to run it now . . . hey, it looks terrible. Turns out we’re missing some CSS definitions. Open up \Content\Site.css and add the following to the bottom of the file:

#mapDiv {

float: right;

}

#dinnerDiv {

float: left;

width: 210px;

background-color: White;

}

#theMap {

position: relative;

width: 500px;

height: 450px;

}

Hit Ctrl-F5 to reload, and you should now get something that looks a lot like the screenshot in the tutorial. Play around with entering addresses and watching your AJAX calls do their magic. Javascript works.

The tutorial suggests changing the Lat/Long to hidden elements. I had already written them in as hidden elements back in Part 7, so there was nothing to change in my code. I encountered an error about missing Lat/Long at one point, but couldn’t repeat it easily. I decided to let it go since this is a toy application only–but note the validations aren’t quite tight here.

Getting the map integrated into Details.aspx was more hassle than it should have been. This time I did copy the code from the tutorial and apply it. I had to add a space between the ContentPlaceHolderID attribute and the runat attribute in the first Content block, and I uppercased to “Map” in the RenderPartial() call, and I noted that the Content block formely named “Main” was now “details” (but didn’t change this, doesn’t matter).

Viewing, the results are functional, but ugly again due to CSS issues. I’m not really a designer and didn’t want to spend a lot of time on this float/height issue. So I cheated and changed Site.css:#main to include a min-height of 400px. That looks nice on the Details page and doesn’t seem to grossly break anything else.

On to location based searching. Add the new user defined functions to the db and drag them into your .dbml, and then add the new method to DinnerRepository.cs as described in the tutorial. We can forget we ever heard of SQL now, it will all be C# from here forward.

Add the new SearchController (don’t add any default methods). You can basically copy the code from the tutorial–take note of the intermediate JsonDinner class. You’ll need to preserve your “using” directives from the original autocreated page, and in a step you’re quite familiar with by now, you’ll need to add using NerdDinner.Models; to those directives as well.  Now we’ve got an access point the client can make requests to, and receive back JSON.  (By the way, isn’t that tidy little Json() call nice?)

(If you’re not familiar with JSON, it is a text format for transferring data. If you’ve used XML to pass data around, JSON works similarly, but JSON is simpler and is more easily used by Javascript–which comes in handy on web pages.)

All that’s left now is getting the client side talking to the server and applying the results. Add the new code to \Views\Home\Index.aspx (put the new HTML at the top of the main content block, and the new javascript at the bottom), then add the two new js functions to Map.js. Note that in the tutorial code, callbackUpdateMapDinners() is missing the final }. You’ll need to fix this. Also notice this method has a typo when setting RsvpMessage–you’ll want to add leading spaces, changing “RSVP” to ” RSVP” and “RSVPs” to ” RSVPs”, or your count and your rsvp will be all one word.

(Did you try mentally stepping through everything in callbackUpdateMapDinners()? That’s another busy one.)

You thought we were done, didn’t you? Not quite. If you try to run the app now, the javascript won’t work. We added script references to Map.ascx, but we haven’t added them here yet. You’ll need to add:

<script src=”http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2″ type=”text/javascript”></script>

<script src=”/Scripts/Map.js” type=”text/javascript”></script>

somewhere in \Views\Home\Index.aspx. (At the top of the main Content block is fine.) Now we can run our new and improved index page. It’s not polished–I got some strange results and some javascript errors while testing–but you should be able to enter a valid address near an existing dinner, see the nearby dinner pushpinned on the resulting map, and test the links that navigate to that dinner (either in the list, or in the popup).

And that’s it for Part 11, and in fact this is the end of all the outwardly visible features for the application. The next, and final, part of the NerdDinner tutorial deals with unit testing (fun!).

You can download my source code for NerdDinner Part 11 here.

NerdDinner Part 10 Discussion and Source Code

Posted in Uncategorized on December 16th, 2010 by matt – Comments Off

This post is a discussion of Part 10 of the online NerdDinner ASP.NET MVC tutorial.

We can’t have a modern web application without AJAX, can we? We’d better get some in NerdDinner.

AJAX is a lot easier if you use a library to manage your calls. The tutorial opts to use MicrosoftAjax.js. I’d have used jQuery myself, but either way works.

Our first code change is to add the IsUserRegistered method to our Dinner model. The code snippet the authors provide is a little confusing. It looks like you replace your entire partial model class with the new IsUserRegistered method.  Don’t do that, just add the new method alongside the other ones already present in Dinner.cs.

Fixing up the Details.aspx view is straightforward. You’ll notice that the the href for the logon link is hard coded as “/Account/Logon” instead of using an ActionLink. Everybody does it the lazy way sometimes. The tutorial shows the RSVP message in red, but it won’t be red with the code we just wrote. You can change this if you like, but I didn’t bother.

Next we create the new RSVPController. Don’t add all the default methods, this controller is very simple. You’ll need to add using NerdDinner.Models; at the top of your controller. As the tutorial points out, we’re not using a view or a partial view, we’re just returning a small snippet of plain text to serve as a reply to the AJAX call.

It’s time to tune up the view. Where should you put the <script> references? Just inside the main Content block is fine. Anywhere that will get rendered, really, we’ll be moving them later. Then change the RSVP section so that it actually does the AJAX call using Ajax.ActionLink(). Don’t miss the new enclosing <div id=”rsvpmsg”>, that’s important. Test your new view out and make sure it’s all working smoothly.

To add some extra visual effects for the RSVP, we’ll use jQuery (did I mention we could have used jQuery for the AJAX call too?). Add the jQuery reference to the <head> of Site.Master (this is under \Views\Shared). If you’re using VS 2010 like me, you’ll need to change the reference from 1.3.2 to 1.4.1 (or, if this too has gone out of date, whatever is in your \Scripts directory for jQuery).

JQuery is a nice library. If you’re not familiar with it, and you want to do any javascript at all, you’ll want to check it out. It’s probably the top pick among all-purpose js libraries these days.

You can add the AnimateRSVPMessage function anywhere that will be rendered, but I’d put it with the other <script> references, easier to move later. Test it out. Watch your message animate and grow large. Unlike the tutorial screenshot, my large message wasn’t red. I let this go too.

Now it’s time to move these changes into their own partial view. When you create your .ascx, don’t forget to make the control strongly typed (to Dinner) and leave the view content empty in the wizard. If you want to follow the spirit of the authoritative NerdDinner source code, when you copy over your RSVP code from Details.aspx, be sure to bring over the AnimateRSVPMessage() function and the two <script> references also.

Create and update the EditAndDeleteLinks.ascx partial, test and make sure everything flies smoothly, and that’s it for Part 10.

You can download my source code for NerdDinner Part 10 here.

NerdDinner Part 9 Discussion and Source Code

Posted in Uncategorized on December 10th, 2010 by matt – Comments Off

This post is a discussion of Part 9 of the online NerdDinner ASP.NET MVC tutorial.

Here we add authentication and authorization using the tools provided by ASP.NET and Visual Studio (which make the whole process shockingly easy).

The early steps of registering a user are straightforward and should “just work”. You can take a look at the Account controller, model and views as the authors suggest, but we won’t be making any changes to them. If you’re curious you can watch the AppData folder using Windows explorer and see the ASPNETDB get created (provided you haven’t created it before now). For some reason, I never got the ASPNETDB to show up under Visual Studio Solution Explorer, but I decided it wasn’t important.

We start code changes by checking authorizations. We do this on the controller methods, and it is just as simple as adding an attribute at the start of the method. Add the Authorize attribute to the two Create method. A minor erratum, you might notice that the example for Create-POST has the Dinner object name as “dinnerToCreate”, but your code has it as “dinner”. Leave it as “dinner” (we’ll be overwriting this method soon anyway).

You may recognize the Authorize attribute as the “extra” attribute that snuck into some earlier NerdDinner code examples. We weren’t ready for it then and had to remove it, but now its time has come.

The tutorial gives a couple of examples of authorizing by user name or role name. These are just examples, don’t write them into your code.

If we’re confident the user is authorized we can use User.Identity property inside the controller method. We do that in Create-POST, automatically creating a self-RSVP along with creating a new dinner, and using the actual user name instead of “SomeUser”. There is a little hitch in the sample code, the catch block shows:

ModelState.AddModelErrors(dinner.GetRuleViolations());

but it should use:

ModelState.AddRuleViolations(dinner.GetRuleViolations());

Fix that, and you should be able to add a new dinner with the automatic identity processing.

Then we tweak the edit methods (also adding a property to the model to support the new changes, and a new view to show if the wrong user tries to edit). Again, you’ll need to change AddModelErrors to AddRuleViolations. Test out the InvalidOwner view and make sure it works as described in the tutorial.

Update the Delete methods to check the owner also. The tutorial mentions this somewhat offhandedly, make sure you actually do it.

Notice that while the Delete methods check to make sure the dinner exists, the Edit methods don’t. The Edit methods should also confirm that the dinner exists before proceeding. I left the Edit methods as they are in the tutorial, but note the omission.

For the last bit of Part 9 we tune up the Details view so that we don’t even show the edit/delete links unless the viewing user is the same as the dinner owner.

In Part 10, we start testing the waters with AJAX. This lets us get our feet wet with AJAX a little bit before the lengthy Part 11 (an interactive map).

You can download my source code for NerdDinner Part 9 here.

Interlude – Sokoban

Posted in Uncategorized on November 10th, 2010 by matt – Comments Off

I took a little detour from NerdDinner to write an ASP.NET version of Sokoban. Sokoban is a simple game that’s often used as a get to know you project for a new language. It’s a fun game, it’s not terribly difficult to code, and when you’re done you can play a few levels as your reward.

Sokoban in ASP.NET MVC

Sokoban in ASP.NET MVC

This implementation uses JQuery to catch keyboard input and to handle the AJAX for the screen updates. If you take a look at the app and you’ve got questions, feel free to drop me a note.

You can download my source code for Sokoban here.

NerdDinner Part 8 Discussion and Source Code

Posted in Uncategorized on November 2nd, 2010 by matt – Comments Off

This post is a discussion of Part 8 of the online NerdDinner ASP.NET MVC tutorial.

Here we implement pagination for the /Dinners/ listing. Admittedly we’re working with a simple example, but it’s quite easy and clean. I like it a lot. If you’ve not worked with LINQ before, you’ll get to see some of what it can do here.

The tutorial first shows us a simplified, hardcoded “slice” of the dinners list (easy to understand), and then improves that example to use an optional pagenumber and page size constant instead.

You should reduce the page size considerably when typing in the example (at least for this part of the walkthrough). Unless you’ve added a lot of dinners to your database, you can’t really see the pagination work with a page size of 10 dinners. I used a pageSize of 3 instead.

When you test with the querystring, notice that the first page is found at page 0, not page 1.

Next we have the routing engine handle URLs of type /Dinners/Page/n to display a paginated view. I’m using .NET MVC 2 as I work through the tutorial, and there are a couple of differences between my code and what the tutorial presents. In my code, the default route uses id = UrlParameter.Optional instead of id=”", and my Application_Start method includes AreaRegistration.RegisterAllAreas() which isn’t in the tutorial code. Here’s the inside of my Global.asax.cs now:

public class MvcApplication : System.Web.HttpApplication

{

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);

routes.MapRoute(

“UpcomingDinners”,                               // Route name

“Dinners/Page/{page}”,                           // URL with params

new { controller = “Dinners”, action = “Index” } // Param defaults

);

routes.MapRoute(

“Default”, // Route name

“{controller}/{action}/{id}”, // URL with parameters

new { controller = “Home”, action = “Index”, id = UrlParameter.Optional }

);

}

protected void Application_Start()

{

AreaRegistration.RegisterAllAreas();

RegisterRoutes(RouteTable.Routes);

}

}

Note that our new route must come before the default route in our route listing. Also, notice the querystring URL still works if we care to use it.

To implement a next/prev for our paging, we create a PaginatedList class. The tutorial is rather coy about telling you where to put this class, but you should add the PaginatedList class to a new PaginatedList.cs file under the /Helpers/ folder. If you add this file to /Helpers/ using Visual Studio, you’ll automatically get the proper namespace and using directives in your file and you can just replace the class definition stub with the code from the tutorial.

Fix up the controller to use the new class. We then need to change the typing for the /Dinners/Index.aspx view to use the new PaginatedList type. The tutorial instructs us to change the inherits statement to look like this:

Inherits=”System.Web.Mvc.ViewPage<NerdDinner.Helpers.PaginatedList<Dinner>>”

but that doesn’t quite work (you’ll get an unknown type error). I needed to include the full namespace for Dinner:

Inherits=”System.Web.Mvc.ViewPage<NerdDinner.Helpers.PaginatedList<NerdDinner.Models.Dinner>>”

Then we update the view itself to give us prev/next links (where they’re appropriate), and we’re done with the code for Part 8. Clever how we ask the routing engine how to write the URL we will send back to the routing engine, isn’t it?

You can download my source code for NerdDinner Part 8 here.

NerdDinner Part 7 Discussion and Source Code

Posted in Uncategorized on October 24th, 2010 by matt – Comments Off

This post is a discussion of Part 7 of the online NerdDinner ASP.NET MVC tutorial.

Here we learn some tricks with view templates: partial pages and master pages.

The tutorial starts with .NET MVC partial view templates. These are a way of encapsulating content to be shared between different web pages. I like the .NET MVC partials. Part 7 is a good example of how they can simplify and clean up your code.

The examples in the tutorial contain a sneaky little problem which will bite you later if you don’t fix it: the code for DinnerForm.ascx doesn’t include Latitude and Longitude! Be sure to include this in your code for DinnerForm.ascx:

<p>

<%= Html.Hidden(“Latitude”, Model.Dinner.Latitude)%>

<%= Html.Hidden(“Longitude”, Model.Dinner.Longitude)%>

</p>

Why use “hidden”? Well, that’s the way it’s handled in the downloaded version of the project. Presumably because it plugs the hole in a simple way (no validation needed). If you preferred, you could use Html.TextBox() instead.

Add the DinnerForm partial template, fix up the create and edit views to use the new partial, and make sure you can do a create and edit successfully.

Take note of the subtle difference between the <%= %> and <% %> code nuggets. (While we’re at it, also note the <%: %> syntax with automatic HTML encoding.) From what I’ve seen, the ASPX view engine is well on the way to being deprecated in practice. Spark is a widely-favored alternative, and Microsoft themselves are promoting Razor for .NET MVC 3. You may never use <%= %> in production.

The tutorial goes on to talk about Master Pages, which you may have already seen in WebForms ASP.NET. If not, the basic idea is to define an overall, consistent layout in a “Master” page, with that master page having a slot for content which most other pages insert themselves into. This is how the different views for the listing, details, and data updates all have the same title and Home and About links, without actually having that HTML in each individual view.

After you read about how Master pages work, you get a little update to the content of Site.master to make our dinner site look a little less placeholdery. There’s a couple of errors in these updates to Site.master. First, it is likely that you’ll want to use <% Html.RenderPartial(“LogOnUserControl”); %> instead of <% Html.RenderPartial(“LoginStatus”); %>. (I’m guessing LoginStatus works with old versions of ASP.NET MVC, but I haven’t checked.) Also, you’ll want to change the action link to <%: Html.ActionLink(“Find Dinner”, “Index”, “Dinners”)%> instead of pointing to /Home/. Here’s what that section of my view code looked like after these corrections:

<div id=”header”>

<div id=”title”>

<h1>NerdDinner</h1>

</div>

<div id=”logindisplay”>

<% Html.RenderPartial(“LogOnUserControl”); %>

</div>

<div id=”menucontainer”>

<ul id=”menu”>

<li><%: Html.ActionLink(“Find Dinner”, “Index”, “Dinners”)%></li>

<li><%: Html.ActionLink(“Home”, “Index”, “Home”)%></li>

<li><%: Html.ActionLink(“About”, “About”, “Home”)%></li>

</ul>

</div>

</div>

. . . and that winds up Part 7. You can download my source code for NerdDinner Part 7 here.

Update:

I messed up. The action links above should include a new link to Create dinners, replacing the home index link.  They ought to look like this:

<li><%: Html.ActionLink(“Find Dinner”, “Index”, “Dinners”)%></li>

<li><%: Html.ActionLink(“Host Dinner”, “Create”, “Dinners”)%></li>

<li><%: Html.ActionLink(“About”, “About”, “Home”)%></li>

Worse, this error was written into the zip file for this chapter and the next few chapters as well. (It gets fixed in Chapter 11.)  At least for now, I’m leaving the zips as they are with this error. You have been warned. You can fix it in your source code now, or keep in sync with my error and use the address bar to navigate to /Create when you need to create a new dinner.

NerdDinner Part 6 Discussion and Source Code

Posted in Uncategorized on October 17th, 2010 by matt – Comments Off

This post is a discussion of Part 6 of the online NerdDinner ASP.NET MVC tutorial.

Here we introduce the idea of the ViewModel, which is an intermediate data structure between the Model and the View.  It’s a common construct and it would probably be more correct to stop saying .NET MVC and start saying .NET MVMVC, which I will do from here forward.  (Ok, I won’t really, but you might find MVPoo amusing.)

Before we start talking about ViewModels, we take a look at the ViewData dictionary. This is a simple way to pass “extra” data from a controller to a strongly typed view. You add a key/value to ViewData in your controller and then you can access it in your view. You can include collections or other complex types as values in the ViewData dictionary (you will need to cast them to the appropriate type in the view).

The tutorial walks us through using the ViewData dictionary to pass a collection of countries (a SelectList), so the view will show a dropdown for Country instead of the original textbox. Fairly straightforward, but there are a couple of bugs.  The Edit-GET method in the tutorial looks like this:

[Authorize]

public ActionResult Edit(int id)

{

Dinner dinner = dinnerRepository.GetDinner(id);

ViewData["Countries"] = new SelectList(PhoneValidator.AllCountries, dinner.Country);

return View(dinner);

}

but it should really be:

public ActionResult Edit(int id)

{

Dinner dinner = dinnerRepository.GetDinner(id);

ViewData["Countries"] = new SelectList(PhoneValidator.Countries, dinner.Country);

return View(dinner);

}

Be sure to remove the Authorize attribute. We’re not ready for that yet, we’ll work with authorization later.

Then, in the Edit-POST method, the catch block looks like this:

catch

{

ModelState.AddModelErrors(dinner.GetRuleViolations());

ViewData["Countries"] = new SelectList(PhoneValidator.AllCountries, dinner.Country);

return View(dinner);

}

but it should look like this:

catch

{

ModelState.AddRuleViolations(dinner.GetRuleViolations());

ViewData["Countries"] = new SelectList(PhoneValidator.Countries, dinner.Country);

return View(dinner);

}

Once you’ve got all that worked out and the Edit view updated, running NerdDinner and editing a dinner will show Country as a dropdown, and your country selection will serve to validate your dinner phone number. (The phone regexes are kind of a pain, honestly. Confusing for non-USA numbers, and they crash the app on a blank phone number. You may want to disable them or otherwise cheat them in your code. Newer versions on CodePlex actually have them removed entirely.)

An alternative to the ViewData dictionary is the ViewModel. Instead of throwing all the “extra” info for a view into a dictionary grab-bag, we explicitly define what will be provided to the view using a class.

The walkthrough starts us off with a new DinnerFormViewModel class, but it doesn’t explicitly say where to put it. Add the DinnerFormViewModel class to \Controllers\DinnersController.cs.

Then let’s race through some minor errata similar to ones we’ve already discussed:

  • In the new class, change the PhoneValidator.AllCountries to PhoneValidator.Countries.
  • When you change the Edit-GET method, be sure you don’t accidentally add the [Authorize] attribute.
  • When you change the Edit-POST method, and again in the Create-POST method, be sure to retain ModelState.AddRuleViolations and don’t replace with ModelState.AddModelErrors.
  • Also, be sure to update \Views\Dinners\Create.aspx to use a DinnerFormViewModel instead of a dinner, and to use the Countries dropdown instead of a text box.

(Note that we rework both the Edit and Create views in Part 7, so you could skip this last update if you feel lazy.)

You can download my source code for NerdDinner Part 6 here.