May 24
Code and Coffee – Inital Impressions
icon1 Darrell Mozingo | icon2 Events | icon4 May 24th, 2009| icon3No Comments »

We’ve had two meet-ups for the Code and Coffee already now, and it seems to be going pretty good. We decided to tackle a simple Rails application, as none of us had used Ruby or Rails before much, and thought it’d be worth taking a look at it.

We’re working through EdgeCase’s Ruby Koans to familurize ourselves with Ruby first, then we’ll start tackling some Rails examples. The Koans are a great way to introduce people to the language. Really, they’re brilliant. The meet-ups have stuck to about an hour in length so far, and we’ve determined we’ll meet every other Friday, still as 7am at the Canton Arabica that was previously mentioned. That puts our next get together on June 5th.

It was only Jason Lautzenheiser, Eric Schliffka, and myself there, but we’re hopeful more people will start coming. There’s been quite a bit of interest, so we’ll see. Looks like these meetings will be pretty helpful, though, keeping all of us on tasks, meeting some new people, and most important, pushing our comfort zone in development terms. They’re pretty fun, to boot! Hope to see you at the next one!

May 23

In part 1, I explained the reasoning behind using strongly typed HTML helpers in your view (with ease of refactoring being chief among them). Now that you have an ASP.NET MVC project referencing the needed Mvc Contrib assemblies, how can you actually get started using them?

Lets start by taking this sexy looking view model that represents a single customer:

public class CustomerViewModel
{
	public int Id { get; set; }
	public string Name { get; set; }
	public CustomerType Type { get; set; }
}

Where CustomerType is a standard enumeration:

public enum CustomerType
{
	Preferred,
	Standard,
	Delinquent
}

Then we’ll provide an easy enough action for editing a customer:

// In reality, we'd take in a customer Id and use that to load the customer from the database.
public ActionResult Edit()
{
	var customerViewModelLoadedFromDatabase = new CustomerViewModel
	                                          	{
	                                          		Id = 10,
	                                          		Name = "John",
                                                    		Type = CustomerType.Standard
	                                          	};
 
	return View("Edit", customerViewModelLoadedFromDatabase);
}

Before looking at the view, though, we’ll need to reference the MvcContrib.FluentHtml.dll assembly, and add the following to our web.config, under the configuration/system.web/pages/namespaces node:

<add namespace="MvcContrib.FluentHtml" />

With all that out of the way, here’s the relevant portion of the edit view:

<% using(Html.BeginForm<CustomerController>(x => x.Update(null))) { %>
	<%= this.Hidden(x => x.Id) %>
 
	<table>
		<tr>
			<td><b><%= this.Label(x => x.Name) %>:</b</td>
			<td><%= this.TextBox(x => x.Name) %></td>
		</tr>
		<tr>
			<td><b><%= this.Label(x => x.Type).Value("Customer Type") %>:</b></td>
			<td><%= this.Select(x => x.Type).Options<CustomerType>().Selected(Model.Type) %></td>
		</tr>
		<tr>
			<td colspan="2" align="center">
				<%= this.SubmitButton("Update Customer") %>
			</td>
		</tr>
	</table>
<% } %>

First, note that the page must inherit from MvcContrib.FluentHtml.ModelViewPage, not the standard Mvc ViewPage class. The strongly typed Html.BeginForm is from the Mvc Futures Assembly. Also, these extensions are on the ModelViewPage base class, not the normal Html helper type methods (i.e. they’re this.TextBox instead of Html.TextBox).

These fields are mostly self explanatory: you’ll see the Id is written to a hidden field on the page using the Hidden extension, the Name using the TextBox extension, and the Type (as a drop down list) using the Select extension. All of these extensions have quite a few customizable methods on them, such as the Options and Selected methods on the Select extension shown above. The options method allows you to specify (via generic type or otherwise with an overload) the options for the drop down, while the selected method allows you to specify which option of the list should be highlighted (it’ll default to the top item if the parameter is null). The Label extension can generate an HTML label “for” the specified control, so by clicking the “Name” or “Customer Type” labels above, most browsers will set focus to their respective controls.

Another quite useful extension is the this.IdFor(x => x.Name), which for our setup would simply output Name, but it comes in handy when dealing with sub objections and collections. This allows you to put a strongly typed reference to your control id’s in Javascript, so renaming the view model’s property renames all references, including the Javascript ones. Huge help there.

Alright, I’ll admit for basic cases like this it’s a bit harder to see the immediate benefits of strong typing, so let’s complicate it a tad by introducing a sub view model for an address, and a collection of order view models by adding this in the Edit action to the customer object initialization:

Address = new AddressViewModel
          	{
          		Street = "123 Easy St.",
          		City = "Beverly Hills",
          		State = "CA",
          		Zip = "90210"
          	},
Orders = new List<OrderViewModel>
         	{
         		new OrderViewModel
         			{
					Id = 300,
         				ApplyDiscount = true,
         				Quantity = 10
         			},
         		new OrderViewModel
         			{
					Id = 301,
         				ApplyDiscount = false,
         				Quantity = 20
         			}
         	}

Here’s one way to modify the edit page to deal with these new objects:

<tr>
	<td><b>Address:</b></td>
	<td>
		<table>
			<tr>
				<td>Street:</td>
				<td><%= this.TextBox(x => x.Address.Street) %></td>
			</tr>
			<tr>
				<td>City:</td>
				<td><%= this.TextBox(x => x.Address.City) %></td>
			</tr>
			<tr>
				<td>State:</td>
				<td><%= this.TextBox(x => x.Address.State).Styles(width => "30px") %></td>
			</tr>
			<tr>
				<td>Zip:</td>
				<td><%= this.TextBox(x => x.Address.Zip) %></td>
			</tr>
		</table>
	</td>
</tr>
<tr>
	<td><b>Orders:</b></td>
	<% for(int i = 0; i < Model.Orders.Count; i++) { %>
		<td>
			<%= this.Hidden(x => x.Orders[i].Id) %>
			<table>
				<tr>
					<td>Quantity:</td>
					<td><%= this.TextBox(x => x.Orders[i].Quantity) %></td>
				</tr>
				<tr>
					<td><%= this.Label(x => x.Orders[i].ApplyDiscount).Value("Apply Discount") %>:</td>
					<td><%= this.CheckBox(x => x.Orders[i].ApplyDiscount)%></td>
				</tr>
			</table>
		</td>
	<% } %>
</tr>

You’ll notice this is all still in a strongly typed manor, even with the sub object and object collection. These are basically the same extensions as before, except for CheckBox, which works as you’d expect. Note the Styles method on most of these extensions, which takes a param of Func’s that allows you to define CSS styles. The state text box, for examples, is defining the width CSS style and setting it to 30px.

All of these extensions take the current ViewData into account when rendering, just as the default ASP.NET MVC extensions do. For instance, the above CheckBox extension will render “checked” if the ApplyDiscount property is true coming in. You can also start to imagine how using the this.IdFor(x => x.property) extension to reference controls in your Javascript would start to come in handy here, as HTML id tag rendering for arrays (where the brackets are replaced with underscores) and sub objects (where dots are replaced with underscores) can get pretty complex.

That pretty much covers the basics of the FluentHTML extensions. These reasons alone were enough to get my team to switch our current project over to using them, let alone some of the more advanced features, such as basic validation integration. I’ll go over a few of those in the next part of this series, though. You can grab a zip of the current project here.

May 8
Code and Coffee
icon1 Darrell Mozingo | icon2 Events | icon4 May 8th, 2009| icon32 Comments »

Coffee and Code

A week or two ago Jason Lautzenheiser emailed around about to a few of us about starting a local Code and Coffee here in the Canton area, and I think it’s a great idea. We haven’t set a schedule or anything, but the first get together will be Friday, May 15th @ 7 AM at Canton Arabica, right on Dressler in Belden. Everyone’s already busy in the evenings, so we figure we’ll give this whole “first thing in the morning” time slot a shot.

Basically we’ll get together to do some pairing on whatever interests everyone, with an eye towards pushing comfort zones (read: new languages and technologies). Very informal. Stop by if you can make it. If we can’t figure out what we’ll do before next Friday, we’ll just call this first one a meet and greet and pick a topic for next time. Since the idea is to pair, don’t worry if you don’t have a laptop.

Don’t fret about the early AM thing. I’m not a morning person myself either (my alarm isn’t even set until 7:20 normally), but it should be good to get the ol’ brain neurons firing that early in the morning.

If you’re interested, let either Jason or myself know. We’re planning on keeping it to about an hour in length.

Hope to see you there!

May 1
2009 Goals – May Update
icon1 Darrell Mozingo | icon2 Goals | icon4 May 1st, 2009| icon3No Comments »

We’re 1/3rd of the way through 2009. How am I doing on my goals for the year? Let’s see (comments in italics after each goal):

Books

  1. Code Complete – Steve McConnell (yep, I’ve never actually read it)    No progress.
  2. Patterns of Enterprise Application Architecture – Martin Fowler    Ordered and on my bookshelf.
  3. Domain Driven Design – Erick Evans    About half way through – good stuff!
  4. Working Effectively With Legacy Code – Robert Martin    No progress.

Tools/Techniques/Processes @ Work

  • NHibernate and all its trimmings (FluentNHibernate, LINQ to NHibernate, etc), which I’ll need on a project here real soon.  Done (though with NHibernate, learning is always ongoing!)
  • Actually move from CC.NET to Team City (last attempt didn’t go so well).  No progress.
  • Build a more robust build script and management process – including production deployment scenarios.   Worked on the script and have a very basic one up and running. The build portion needs a lot more refinement before I get anything more advanced in there though.
  • Messaging framework, either MassTransit, NServiceBus, or Ayende’s new Rhino Service Bus if he’s able to release it in time for our current project.  No progress as we haven’t needed any yet.

Involvement

  • We have weekly meetings to catch everyone up on what we’re doing, but I want to present on an actual topic during at least 2 of these – and present in a way where the other development teams will see the use in picking up the presented tool/technique.    Our meetings were/are halted for a bit, but I think an intro IoC/DI presentation when they pick back up in a bit is in order.
  • Have at least one meeting of the CantonALT.NET group and see if it can ever get up on its feet.   No progress.
  • The two blog posts per month target John put out there seems doable, so I’ll borrow it 🙂    Sorta keeping on target – I didn’t really have two substantial ones in March, but I made up for it (just in time yesterday!) by doing 3 in April.
  • At least 3 feature/patch submissions to open source projects.  Submitted quite a few patches (some small, some a bit meatier) to the MVC Contrib project and one (yet unaplied) one to the xVal project. So while I guess this goal is technically met, I’d still like to do something of a little more substance to push myself.

Productivity

  • Trim RSS feed size by 1/3 (presently at 127, so trim it to at least 85) and cut time viewing it by half. I’ve gotten much better this past year at cutting through the useless stuff, but there’s still a lot there and it sucks up too much of my time.  Down a bit to 116. Hey, it’s a start!

Starting on the reading was good, but only half a book in two months is pretty sad. Everything else is more or less on schedule, but I need to start thinking about that CantonALT.NET meeting (or something similar).

I’ll update again in the begining of July.