# Wednesday, September 3, 2008

Ten years ago, I showed up for my first meeting with my first customer while working at my first consulting job.  The customer was a dressmaker in suburban Philadelphia and I flew out to meet the IT Manager.

Everything went wrong. 
-The receptionist at my office erroneously told the customer that I would arrive first thing in the morning, even though my flight was scheduled to land after noon. 
-The customer was already disappointed by the quality of work delivered to date and had transferred at least part of his blame to me.  "This is your last chance", he told me during our first meeting, even though it was also my first chance. 
-The project was in a horrible state.  It was already past due and over budget when it was assigned to me.  The existing code as an undocumented mess of spaghetti logic, riddled with bugs.  Further it contained no logging or even graceful error handling.  When the program encountered an error, it simply crashed.

After a few months flying across country and working long hours, I was able to get the project quality to a level that was acceptable to the customer. 

But at that first meeting, I was completely confused and thoroughly intimidated.  I was there to help the customer but our relationship felt adversarial from the start.  I did not manage that first meeting well at all.

Since that time, I have had hundreds of first meetings with customers and I have gradually become better at managing that first encounter.

Given my disastrous first day on site, this article serves to give you the benefit of my ten years of trials and errors.  I like to believe that I learn from my mistakes and now you can also learn from my mistakes.

So here are my rules for a consultant’s first meeting with a new customer.
Rule 1: Listen
Rule 2: Don't solve the problem too soon
Rule 3: Set expectations
Rule 4: Do your homework
Rule 5: Other rules

Rule 1: Listen

This is the first rule because it is by far the most important.  You want your customer to describe his pain points for you and you want to have an understanding of those pain points and why they are causing problems.

Most of the time, a consultant is brought in because the customer wants to change something.  Find out what is driving his desire for change. 

Sometimes the customer has a detailed map of where he wants to go; sometimes he has no clue; sometimes he can see part of the solution; and sometimes he thinks he knows the solution but is on the wrong track.  Listen to what he has to say before deciding into which group your customer falls. 

Try not to interrupt, but ask relevant questions to clarify anything you don't understand.  Customers sometimes use jargon that they understand but you do not.  Ask for definitions when these terms come up.

Take good notes.

When the customer finishes, echo back your understanding of what you heard.  You can do this immediately or in a follow-up e-mail shortly afterward.

Rule 2: Don't solve the problem too soon

This point is related to the last one. Consultants and technical people tend to be problem solvers.  If we hear a problem and think we know the answer we want to shout out that answer to show off how smart we are.  (Okay, maybe you don’t; but I find myself fighting this urge all the time.  I’m a show-off and I’ve met many like me in the consulting industry, so I’ll stereotype here.) 
Most customers (another stereotype coming now) hate this.  If you tell them what they need before they describe their problem, you come across as arrogant, sloppy and uncaring. 
Your first idea may be correct but you should verify this before shooting off your mouth.  Of course, there is always the chance that the customer may know more about his own business and his own problems than you do.

It’s okay to ask questions, such as “Have you thought about this?” or “Have you ever tried this?” but be careful.  Don’t come across as suggesting that you know the answers before he even asks the question.  You are likely to lose credibility before you start.

Rule 3: Set expectations

I am a firm believer that every meeting should have an agenda.  For the first customer-facing meeting, you need two agendas:
1) What will be discussed at this meeting?
2) What will be the responsibilities and expectations of each person during the project?

Many projects fail because those involved don’t know what they are expected to deliver.  Assumptions can be fatal to any project because it is unclear who should be working on what.

Although each project is different, here are a few common questions worth clarifying
-Does the customer want a prototype or a production-ready application? 
-What is your role?
-Is the design complete?  
-Are you expected to lead or participate in the design? 
-Does the customer want you to mentor some of their team members?
-Are there any dependencies you need to be aware of?  What is the contingency plan if a dependency is not met?

You don’t need to answer all these questions at this first meeting but you should talk about them early in the project.  And you should leave the first meeting with an idea of the scope of the project and your role on it.

Rule 4: Do your homework

Before arriving at your first meeting, you should make an effort to find out what you can about the customer and his problem. 

Many times, a salesperson or project manager will have already spoken with the customer.  Talk to these people and get their take on what the customer wants.  Don’t accept that the salesperson has provided 100% of the information.  Several times, I have heard a customer describe a completely different problem than the one described to me by the customer.  (See Rule 1 for how to prevent this miscommunication).

Use the World Wide Web to learn at least the core business of the customer’s company. 

A little preparedness creates a good first impression and provides some context for your opening conversation. 

Rule 5: Everything else

Here are a few more bits of advice I’ve picked up over the years.
-Be on time.  Verify the scheduled time and plan to get there early if possible.
-Dress a little better than the customer.  This advice is often given for job interviews and I think it applies here as well.
-Avoid jargon and acronyms unless you are certain that the customer is familiar with the terms you use.  Your goal is to communicate and jargon often gets in the way of that goal.
-Don't take it personally.  I've had customers blame me for the mistakes of other consultants (some of whom worked for other companies), for the quality of Microsoft software, and for the health of their business.  In nearly every case, they are blowing off steam.  You should make every effort to keep the conversation on topic and the topic is: "What are your problems and how can I help you to solve them?".

Conclusion

The above list of advice is certainly not exhaustive but my experience has shown these to be the most important points when meeting a customer for the first time. 

Wednesday, September 3, 2008 6:09:25 PM (GMT Daylight Time, UTC+01:00)
# Wednesday, August 27, 2008

Microsoft recently released the ASP.Net Model View Controller framework (MVC).  It is currently available as Preview 3 and can be downloaded at http://www.microsoft.com/downloads/details.aspx?FamilyId=92F2A8F0-9243-4697-8F9A-FCF6BC9F66AB&displaylang=en

A new MVC project contains a couple sample views and controllers so you can get an idea of the proper syntax to use. 

This article builds on the application created in my last ASP.Net MVC tutorial.  If you have not already done so, please follow the brief states in the previous MVC tutorial before beginning this tutorial

In the last tutorial, we added a model, view and controller to display a list of customers that one can navigate to using a URL formatted as controller/action.  In this article, we will add a new view and controller to an existing MVC project and display details of a single customer using a URL formatted as controller/action/id.  The id is passed automatically to the action method and allows us to filter to a single customer.

1.       Open Visual Studio 2008 and open the TestMVC solution created in MVC Tutorial 2.

2.       Open the Solution Explorer (View | Solution Explorer) and select the Controllers\CustomerController.cs.   Double-click CustomerController to open it in the code editor.

a.       In the CustomerController class, we will create a new action to get the details of a single customer.   

                                                               i.      Add the following private GetCustomer method to the CustomerController class.  In the last tutorial, we wrote methods to retrieve customer 1 and customer 2.  For simplicity, we will get Customer 1 if ID 1 is passed in to our method and Customer 2 if any other ID is passed.

        private Customer GetCustomer(int custID)

        {

            if (custID == 1)

            {

                return GetCustomer1();

            }

            else

            {

                return GetCustomer2();

            }

        }

                                                             ii.      Add an Action method to the CustomerController class to get the details of a customer.  Paste the following code into CustomerController.cs.

        public ActionResult Details(int id)

        {

            Customer cust = GetCustomer(id);

            return View("Details", cust);

        }

                                                            iii.      In the GetCustomer method, we get details of a single customer and return a view.  Unlike the generated code, we explicitly specify which view to return (“Details”) and we pass in some extra data (cust) that the view will consume.

3.       Add a view to the project.

a.       In the Solution Explorer, right-click the Views\Customer folder and select Add | New Item.  The Add New Item dialog displays.

    Figure 1

                                                               i.      Under Categories, select Visual C#\Web\MVC.

                                                             ii.      Under Templates, select  MVC View Content Page.

                                                            iii.      In the Name textbox, enter “Details”.

                                                           iv.      The Select a Master Page dialog displays.  

   Figure 2

1.       Navigate to the Views\Shared folder and select Site.Master.

2.       Click the OK button to add this view content page to the project.

b.      Add visual elements to the View

                                                               i.      If it is not already open, open the Details view by double-clicking List.aspx in the Solution Explorer.  Click the Source tab at the bottom of the editor.

                                                             ii.      Replace the code in Details.aspx with the following

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Details.aspx.cs" Inherits="TestMVC.Views.Customers.Details" %>

<%@ Import Namespace="TestMVC.Views.Customers"%>

<%@ Import Namespace="TestMVC.Models" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

    <div>

        CustID:

        <%=((Customer)ViewData.Model).CustID %><br />

        Name:

        <%=((Customer)ViewData.Model).FirstName %>

        <%=((Customer)ViewData.Model).LastName %>

        <br />

        Address:

        <%=((Customer)ViewData.Model).StreetAddress%><br />

        City:

        <%=((Customer)ViewData.Model).City %><br />

        State:

        <%=((Customer)ViewData.Model).State %><br />

        ZIP:

        <%=((Customer)ViewData.Model).PostalCode%><br />

    </div>

 

</asp:Content>


The above code displays details of a single Customer model object. 

4.       Modify the List view

a.       Open Views\Customers\List.aspx by double-clicking it in Solution Explorer.

b.      Find the <td>&nbsp;<\td> cell tag following the cust.PostalCode cell.  Replace this with the following code.  This generates a hyperlink displaying the text “Details”.  The URL of the hyperlink will have the current controller (“Customer”) the “Details” Action and the ID of the current customer.

<td>

<%=Html.ActionLink("Details", "Details", new { ID=cust.CustID})%>

</td>

5.       Test the application

a.       Save and compile the solution (Build | Build Solution).   Correct any errors you find.

b.  Run the solution (Debug | Start Debugging).  Depending on the port number used by Casini, it should display in your browser with a URL such as
http://localhost:4152/Home

c.       Navigate to the List page by changing the URL to
http://localhost:4152/Customers/List
(Replace the port number if necessary)

d.      You should see a list of 2 customers in your browser.  Each customer should have a hyperlink labeled “Details”. 

    Figure 3

e.      Click the hyperlink next to customer 1.  The URL should change to
http://localhost:4152/Customers/Details/1
and the details of the first customer should display on screen.

    Figure 4

f.        Set a breakpoint in the Details method of CustomerController.cs and refresh the page to step through the code as it executes.

In this article, we added a view and controller to our application and used these to retrieve and display customer details by the Customer ID. 

.Net | ASP.NET | MVC
Wednesday, August 27, 2008 1:26:29 PM (GMT Daylight Time, UTC+01:00)
# Tuesday, August 26, 2008

There's nothing quite like riding on a bus for 27 hours with a few dozen software developers.

That's exactly what I did last weekend on my way to and from DevLink in Murfreesboro, TN.

The DevLink bus was the result of much hard work by Amanda who did most - if not all - the organizing.

The bus began its odyssey Wednesday night in Grand Rapids, MI before proceeding to Lansing.  When the bus picked me up in Plymouth, MI at 9:15 PM, it had already been traveling for 3 hours.  From there, it rolled on to Toledo, Columbus and Cincinnati (its final southbound stop at 4AM) before proceeding to its final destination in Murfreesboro, Tennessee. 

The first half of the ride was great fun.  I met new people; I reconnected with old friends; and I met people face-to-face with whom I had only communicated electronically.

Event the two times the bus driver got lost couldn't dampen our spirits.  We were having too much fun.

After about 4AM, the trip began to drag.  Everyone was exhausted and the seats were too uncomfortable to allow more than a few minutes sleep at a time.  This was clearly a bus designed for cross-town trips – not cross-country trips.  DVDs provided some entertainment ("The Big Lebowski" and “Office Space” cracked me up) but you can only focus on movies for so long and the acoustics were less than ideal.

We arrived at our hotel worn and weary at 9:30AM Central time, over 13 hours after leaving Plymouth and 16 hours after the bus began its trip. 

24+ hours of sleep deprivation left me physically ill and I spent nearly all of Thursday in bed.

It was good that I did.  The conference began Friday morning and I awoke refreshed and ready to absorb and exchange ideas at what turned out to be an excellent conference.  (You can read more about it here.)

The ride home was an adventure.  Although the conference ended at 6PM, someone decided the bus shouldn't leave town until 9PM so we had to kill a few hours at a restaurant before heading out. 

Although we picked up at least one new traveler on the ride home, we lost a few more.  Some folks booked a flight to Chicago for a Monday business meeting and a couple people elected to rent a car and drive home rather than subject themselves to the length and discomfort of the bus ride.  I was tempted to join them but I stuck with my plan and boarded the bus at 9.

The mood was more subdued on the return trip. We still had some good conversations early in the ride but the environment lacked the energy sparked by seeing people for the first time in months.

About 2AM, I had just begun to drift to sleep when a sound like a jackhammer awakened me suddenly.  I was sitting just above the tire that blew flat traveling 65 miles an hour on I-71 just north of Louisville, KY.  We pulled off the highway in front of a Waffle House in Carrolton, KY and waited 3 hours for the tire to be fixed.  The repair would have taken far less time if the repair guy had not allowed a drunken Waffle House customer to play with the lug nut gun.  He sheared off the bolts on wheel, forcing the repair guy to return to his shop for more parts and weld on new bolts.

Waffle House provided some entertainment.  Corey attempted to start a relationship with one of the waitresses; and the manager tossed out a drunk who wouldn't stop ordering pork chops long after he was told the restaurant was out of pork chops.  Apparently the Carrolton Waffle House is a magnet for drunks at 2AM Saturday night.  Go figure.

We got back on the highway about 5AM so exhausted that even the uncomfortable seats wouldn't prevent a few hours dozing.

I thought things would go quicker after this because the drivers knew the route better, having just driven it 3 days earlier.  Alas, we became lost in northeast Ohio and drove nearly to Cleveland before turning west toward Toledo.

At 12:30 Eastern time - 14.5 hours after leaving the hotel and 17.5 hours after the end of the conference - we pulled into the parking lot in Plymouth.  I was never so happy to see my car and the 40 minute drive home seemed trivial. 

I was scheduled to read aloud at the 12:15 mass in my church and the last minute substitute is probably still angry with me for missing this, but we all arrived safely.

Was the bus ride a success?  Would I do it again?  Would I take a bus to a distant location with dozens of others like me?  I've decide that, if I can be promised a more comfortable seat, I will do it the next time it's offered.  Everything else was easily tolerable and I did enjoy the fellowship that came with such a long ride with like-minded people.  I even got a few job leads from the conversations I had on the two rides (I am between jobs for those who don't know).

If you go on such a trip, my only advice is

  1. Be prepared for anything
  2. If the Waffle House waitress in Carrolton, Ky tells you they are out of pork chops, shut up and order the hash browns. 

Note: Click here to see more photos from DevLink and the famous bus ride.

Tuesday, August 26, 2008 4:38:58 PM (GMT Daylight Time, UTC+01:00)

People attend conferences for many different reasons.  Some come for the content of the lectures; some come to meet and hear well-known speakers; some come to meet and network with others in the industry; some come to see old friends.

Me, I come for all those reasons.  At DevLink last week in Murfreesboro, TN, I experienced all those things and more. 

But I also experienced something new.  I had heard of Open Spaces in the past but had not experienced them.  At DevLink, Open Spaces were promoted heavily as a different way of exchanging ideas.  I was curious and gave it a try.

An Open Space event consists of developers sitting together roughly in a circle in a room and they exchange ideas with one other.  A topic is picked in advance by the group but the conversation is not limited to that topic.  If the conversation drifts from the assigned topic and the group remains engaged, this is perfectly all right.  The important thing is that ideas are exchanged and the group remains passionate about the conversation.

And I heard a great deal of passion at the DevLink Open Spaces that I attended.

During the event, I attended 3 Open Spaces sessions plus the planning session (where topics were picked) and the wrap-up session (where the group reviewed the open spaces of the previous 2 days).  In each session I attended, I heard bright people sharing great ideas.  Sometimes we argued and sometimes we were in violent agreement but I enjoyed it all. 
In a session on Service Oriented Architecture, I argued earnestly that, due to the costs of SOA, support from the top was necessary for SOA to succeed within any organization.  Most of the other loud persons in the group insisted that newer tools such as WCF had lowered the cost of SOA sufficiently that a strong grass roots effort could drive SOA in an organization.  By the end of the session, I think we had all learned something and moved a little toward understanding the others' side.

I did attend a few traditional sessions in which a speaker stands in front of a classroom and delivers a lecture to an audience that is mostly passive.  Richard Campbell and Carl Franklin were two of the speakers at this conference and I have long been a fan of their .Net Rocks podcast, so I made a point to attend a lecture by each of them.  Both were good sessions but they were easily topped by Joe Wirtley who gave an excellent talk on WPF.  It was excellent because it focused on building a business application, rather than the eye candy that clutters so many WPF presentations.

Overall the conference was a great success.  It drained me of energy but it fired me up at the same time.

And I haven't even told you about the 28 hours I spent riding a bus with a few dozen techno-geeks.  Or the flat tire that left us stranded in Carrolton, KY for 3 hours at 2AM.  But that’s another story.

Note: Click here to see more photos from DevLink

Tuesday, August 26, 2008 4:49:27 AM (GMT Daylight Time, UTC+01:00)
# Friday, August 22, 2008

Microsoft recently released the ASP.Net Model View Controller framework (MVC).  It is currently available as Preview 3 and can be downloaded at http://www.microsoft.com/downloads/details.aspx?FamilyId=92F2A8F0-9243-4697-8F9A-FCF6BC9F66AB&displaylang=en

A new MVC project contains a couple sample views and controllers so you can get an idea of the proper syntax to use. 

In this article, we will add a new model, view and controller to an existing MVC project. 

1.       Open Visual Studio 2008 and create a new MVC project.  For information on how to create a new MVC project, see http://www.davidgiard.com/2008/08/18/TheASPNetMVCSampleAppDemystified.aspx

2.       Open the Solution Explorer (View | Solution Explorer) and select the Models folder.

3.       Add a Model to the project

a.       Right-click the Models folder and select Add | Class.  The Add New Item dialog displays.
Figure 1
    Figure 1

                                                               i.      At the Name textbox, enter “Customer”.

                                                             ii.      Click the OK button to create a Customer class.

b.      The Customer class opens in the class editor.  This class will contain a few public properties that help describe a customer object.  Add the following code to the Customer class.

    public class Customer

    {

        public int CustID { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string StreetAddress { get; set; }

        public string City { get; set; }

        public string State { get; set; }

        public string PostalCode { get; set; }

    }

4.       Add a Controller to the project

a.       In the Solution Explorer, right-click the Controllers folder and select Add | New Item.  The Add New Item dialog displays.
Figure 2
    Figure 2

                                                               i.      Under Categories, select Visual C#\Web\MVC.

                                                             ii.      Under Templates, select MVC Controller Class.

                                                            iii.      In the Name textbox, enter “CustomerController”.

                                                           iv.      Click the Add button to create the CustomerController class and open it in the class editor.

b.      In the CustomerController class, we will create some actions.  Each action will instantiate one or more Model objects and display them in a view object. 

                                                               i.      Add the following statement at the top of the CustomerController class. 

using TestMVC.Models;

                                                             ii.      Add the following private methods to the CustomerController class.  For now, we will create customers out of thin air (as if it were that easy).  In a real application, we would probably call a web server or query a database to get customers.

        #region private methods

        private Customer GetCustomer1()

        {

            var cust1 = new Customer

            {

                CustID = 1,

                FirstName = "David",

                LastName = "Giard",

                StreetAddress = "123 Main",

                City = "Boringville",

                State = "MI",

                PostalCode = "48108"

            };

 

            return cust1;

        }

 

        private Customer GetCustomer2()

        {

            var cust2 = new Customer

            {

                CustID = 2,

                FirstName = "John",

                LastName = "Smith",

                StreetAddress = "321 Elm",

                City = "Nowhere",

                State = "OH",

                PostalCode = "41001"

            };

 

            return cust2;

        }

 

        private List<Customer> GetAllCustomers()

        {

            Customer cust1 = GetCustomer1();

            Customer cust2 = GetCustomer2();

            List<Customer> allCusts = new List<Customer> {cust1, cust2};

            return allCusts;

        }

 

        #endregion

                                                            iii.      Add some Action method to the CustomerController class.  We’ll start with a List action.  Paste the following code into CustomerController.cs.

        public ActionResult List()

        {

            var allCustomers = GetAllCustomers();

            return View("List", allCustomers);

        }

                                                           iv.      In the List, we get a list of customers (all 2 of them) and return a view.  Unlike the generated code, we explicitly specify which view to return (“List”) and we pass in some extra data (allCustomers) that the view will consume.

5.       Add a view to the project.

a.       In the Solution Explorer, right-click the Views folder and select Add | New Folder.  A new folder appears in the Solution Explorer.  Rename this folder to “Customer”.

b.      In the Solution Explorer, right-click the Customer folder and select Add | New Item.  The Add New Item dialog displays.

                                                               i.      Under Categories, select Visual C#\Web\MVC.

                                                             ii.      Under Templates, select  MVC View Content Page.

                                                            iii.      In the Name textbox, enter “List”.

                                                           iv.      The Select a Master Page dialog displays. 
Figure 3
   Figure 4

1.       Navigate to the Views\Shared folder and select Site.Master.

2.       Click the OK button to add this view content page to the project.

c.       Add visual elements to the View

                                                               i.      If it is not already open, open the List view by double-clicking List.aspx in the Solution Explorer.  Click the Source tab at the bottom of the editor.

                                                             ii.      Replace the code in List.aspx with the following

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="List.aspx.cs" Inherits="TestMVC.Views.Customers.List" %>

<%@ Import Namespace="TestMVC.Views.Customers"%>

<%@ Import Namespace="TestMVC.Models"%>

 

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

    <h2><%= Html.Encode(ViewData["Message"]) %></h2>

    <table>

        <tr>

            <td>ID</td>

            <td>First</td>

            <td>Last</td>

            <td>Addr</td>

            <td>City</td>

            <td>State</td>

            <td>ZIP</td>

            <td>&nbsp;</td>

        </tr>

        <% foreach (Customer cust in (List<Customer>)ViewData.Model)

           { %>

            <tr>

                <td><%=cust.CustID %></td>

                <td><%=cust.FirstName%></td>

                <td><%=cust.LastName%></td>

                <td><%=cust.StreetAddress%></td>

                <td><%=cust.City%></td>

                <td><%=cust.State%></td>

                <td><%=cust.PostalCode%></td>

                <td>&nbsp;</td>

            </tr>

        <% } %>

    </table>

</asp:Content>


The above code displays a list of Customer model objects.  In a real-world example, we may choose to have the Customer model derive from a base class and only refer to the base class in the view.  This would increase the separation between our view and our model.

6.       Test the application

a.       Save and compile the solution (Build | Build Solution).   Correct any errors you find.

b.  Run the solution (Debug | Start Debugging).  Depending on the port number used by Casini, it should display in your browser with a URL such as
http://localhost:4152/Home

c.       Navigate to the List page by changing the URL to
http://localhost:4152/Customers/List
(Replace the port number if necessary)

d.      You should see a list of 2 customers in your browser
Figure 4
    Figure 4

e.      Set a breakpoint in the List method of CustomerController.cs and refresh the page to step through the code as it executes.

In this article, we created a model, view and controller from scratch and displayed them.  You can download the code for this project here.

In the next article, we will use the ID of the URL to specify a single customer.

.Net | ASP.NET | MVC
Friday, August 22, 2008 2:02:34 PM (GMT Daylight Time, UTC+01:00)
# Thursday, August 21, 2008

I have been plagued recently by a recurring problem with Visual Studio 2005.

When I attempt to exit Visual Studio, I receive the error "Visual Studio cannot shut down because a modal dialog is open" and I am not able to exit.  The rub is that there is no modal dialog - close every visible window in VS, close all other apps, resize, move and minimize VS and I can find no dialogs, modal or otherwise.  Some bit inside VS is set incorrectly convincing itself that a dialog has not yet been closed.

The only solution was to open Task Manager and kill Visual Studio.

I have automatic updates turned on so, if this is a bug, I expected it would have been fixed by now. 

I found a number of posts and threads about this issue so it is not uncommon but nearly every post did not list a solution.

After some digging, I discovered a hotfix for this problem that is not included in the normal Windows updates. 

You can read the details of the problem from Microsoft here http://support.microsoft.com/kb/936971 and you can download the hotfix here
https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=7259

One important point.  Visual Studio must be closed before installing the hotfix so you may end up killing the process via Task Manager one last time.

Thursday, August 21, 2008 12:51:23 AM (GMT Daylight Time, UTC+01:00)
# Tuesday, August 19, 2008

Every year, I become a bit more accepting of my own ignorance. 

I decided a long time ago that I wanted a career in which I could continue to learn and to expand my knowledge.   Software development affords me that opportunity because it is such a large field and because it changes so rapidly. 

It is conceivable (though extremely unlikely) I could learn everything there is to know about software development and find myself completely caught up with learning for one day.  If that miracle were to occur however, I would go to bed that night and awaken to discover that things had been invented while I slept.  And I would once again be ignorant about some things.

But that day will never come.  There is an infinite amount of knowledge to be acquired and a finite amount of time in which to learn it.  The ratio of what I know to what I don't know is likely to remain small.

Yesterday, I had lunch with a guy who knows a great deal about Windows Presentation Framework (WPF).  Since I am extremely ignorant about WPF, it was a good opportunity to learn some new things.  But WPF contains so much that we could probably have lunch every day for months and I would still only scratch the surface of this framework. 

I want to know everything but I realize and accept that I cannot.  So what's the answer? 

The answer is in learning how to find the answers.  "I don't know" is an acceptable answer to any question, but "I can't do it" is not.  As new challenges and problems arise, we need to be able to figure them out - to find the answer.  Usually our experiences only get us so far.  We need help finding answers. 

Certainly the World Wide Web helps.  Many times, when faced with a problem, I've discovered an article or blog post written by a developer who faced and conquered a similar problem.  Search engines such as Google allow us to find these solutions more quickly. 

Books and magazines help as well.  They provide knowledge based on the experiences of the authors.  So do Classes and conferences.

I've found one of the best ways to improve my knowledge base is to build a network of smart people on whom I can call for tough questions.  I try to reciprocate as much as I can, but luckily software developers tend to be very generous with their ideas.

So the conclusion I've come to after all this introspection is that what we know is not nearly as important as what we are capable of finding out. 

And that's encouraging for a guy like me who will never know it all.

Tuesday, August 19, 2008 4:59:22 PM (GMT Daylight Time, UTC+01:00)
# Monday, August 18, 2008

Microsoft recently released the ASP.Net Model View Controller framework (ASP.Net MVC).  It is currently available as Community Technology Preview 3 and can be downloaded at http://www.microsoft.com/downloads/details.aspx?FamilyId=92F2A8F0-9243-4697-8F9A-FCF6BC9F66AB&displaylang=en

This article describes how to create an ASP.Net MVC application and the code that is auto-generated for you.

Creating a new ASP.Net MVC project

1.       Open Visual Studio 2008.  Create a new project: Select File | New Project.  The New Project dialog displays.

    Figure 1

a.       Under Project Type, select Visual Basic\Web or Visual C#\Web, depending on your language preference.

b.      Under Templates, select ASP.Net MVC Web Application.  This application was added when you installed the ASP.Net MVC preview.

c.       Provide an appropriate location and name for the project and solution.

d.      Click the OK button to create the project.

2.       One of the advantages of an ASP.Net MVC project is that the separation of most of the code from the user interface makes it easier to write unit tests.  Visual Studio encourages you to create unit tests for your new project by prompting you with the Create Unit Test Project dialog every time you create an MVC project.

    Figure 2

a.       If you wish, you can decline to create a Unit Test project or you can change the default project name.  Typically I do not change any defaults on this dialog.

b.      Click the OK button to create the Unit Test project.

The Folder structure of an MVC project

When you create a new MVC project, Visual Studio, generates a couple views and controllers.  If you understand how these work, you can use them to guide how you will create more views and controllers.

The solution contains two projects: an MVC project and a unit test project.

View the projects in Solution Explorer.  Select View | Solution Explorer.  The MVC project contains several folders.


    Figure 3

1.       The Content folder contains a stylesheet Site.css for this site.

2.       The Controllers folder is where you will store all your controller classes.  By default, this folder contains a single controller class - HomeController.cs.

3.       The Models folder is where you will store any model classes for your application.

4.       The Views folder contains a subfolder for each view in your application.  By default, there are two subfolders: Home and Shared. 

a.       The Shared subfolder contains a master page for the site because it is shared by multiple web pages.  Any other UI elements shared by the site belong in this folder.

b.      The Home folder contains two pages: About.aspx and Index.aspx. 

5.       As with most web applications, the root folder of this project contains a Global.asax file and a Web.Config file, which contain setup and configuration information for the application as a whole.

The Files and Folders of an MVC project

Open Global.asax and view the code.  Notice that the Application_Start method (which fires once, at the startup of the web application) contains a call to the RegisterRoutes method. The RegisterRoutes method tells the MVC framework how to interpret a URL. 

public static void RegisterRoutes(RouteCollection routes)

{

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

 

    routes.MapRoute(

        "Default",                                              // Route name

        "{controller}/{action}/{id}",                           // URL with parameters

        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults

    );

 

}

The routes.MapRoute method accomplishes this.  In this case, a “Default” route collection is created that interprets a URL with syntax like “{controller}/{action}/{id}”. 

·         The first part of the URL specifies the controller to use.  MVC looks in the Controllers folder for a class that inherits from System.Web.Mvc.Controller with a name that matches the controller specified in the URL.

·         The second part of the URL specifies the action to take.  The action is the public method within this controller that will be called. 

·         The third part of the URL specifies an id to pass to the action method.  This can be used to further customize the action.  For example, we could use the id as a filter to dynamically look up a single row in a database.

The routes.MapRoute method also allows us to specify defaults if no controller or action or id is specified in the URL.  If any of these are omitted from the URL, MVC will use the defaults specified in the third parameter of routes.Maproute.  In this case the object new { controller = "Home", action = "Index", id = "" } tells MVC the following:

·         If no Controller is specified in the URL, assume the Home controller (i.e., look for a class named “Home.cs” in the Controllers folder).

·         If no Action is specified in the URL, assume the Index action (i.e., look for a public method “Index” in the Home.cs class).

·         If no ID is specified in the URL, assume a blank ID (i.e., any code looking for an ID will retrieve an empty string).

Open the view files: Home.aspx and About.aspx and notice that there is no code behind in either.  This is because ASP.Net MVC applications do not execute the page life cycle.  All the code for this application is in the controllers.  These view pages contain only visual elements.

Open the controller class: Homecontroller.cs.  As we mentioned before, this class derives from the System.Web.Mvc.Controller class and it contains two methods: Index and About.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

 

namespace TestMVC.Controllers

{

    public class HomeController : Controller

    {

        public ActionResult Index()

        {

            ViewData["Title"] = "Home Page";

            ViewData["Message"] = "Welcome to ASP.NET MVC!";

 

            return View();

        }

 

        public ActionResult About()

        {

            ViewData["Title"] = "About Page";

 

            return View();

        }

    }

}

“HomeController” is the name of the class to implement the Home controller.  This is typical of how MVC works – developers follow naming conventions in order tell the framework where to find the code to run.  In the case of controllers, we implement a controller by sub-classing the System.Web.Mvc.Controller class, naming this subclass “xxxController” (where xxx is the Controller name) and placing that subclass in the Controllers folder of our MVC project.  If we wanted to call a controller named “David”, we would create a System.Web.Mvc.Controller class named “DavidController” into the Controllers folder.  This process is known as “convention over configuration”, meaning that the framework knows where to find code based on the names we use.

Let’s look closely at the Index method.  Recall that the method in the controller is the Action that is specified in the URL.  So the Index method will be called if the Index action is specified.

ViewData is a dictionary collection that is a property of every Controller object.  We can add or update items in this collection by syntax such as
ViewData["Title"] = "Home Page";

By placing items in this collection, we make them available to the view when it is called.

The view (remember this is the UI that the user will see) is returned from this method.  The following line returns the default view.
return View();

We know it is the default view because the statement did not specify the name of the view.  The default view has the same name as the Action called.  In this case, we are returning the Index view.  Once again, MVC uses conventions to determine where to find the view.  All views associated with a given controller are stored in a subfolder named for that controller beneath the Views folder.  In this case, we are using the Home controller, so we look for views in the Views\Home folder of the project.  The view itself is a file with the same name as the view and with an extension of “.aspx” or “.ascx”.  In this case, we are looking for the default view (Index) of the Home controller.  MVC renders the page Views\Home\Index.aspx for this view.  Again, the developer uses naming conventions to tell the framework where to find items.

Open Index.aspx.  Notice it displays the message stored in the ViewData dictionary by the controller.
<%
= Html.Encode(ViewData["Message"]) %>

However, it contains no other code, because all logic is handled by the controller.

Conclusion

Creating a new ASP.Net MVC project is as easy as creating any other Visual Studio project.  Learning the paradigm that the MVC framework uses can be a challenge; but the samples created automatically with a new project can ease that learning curve.

In the next article, we will add a new controller and view to a project.

.Net | ASP.NET | MVC
Monday, August 18, 2008 4:37:58 PM (GMT Daylight Time, UTC+01:00)
# Sunday, August 17, 2008

The Model-View-Controller (MVC) design pattern has existed for years.  (http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html)  ASP.Net developers have been implementing it for years either through their own custom code or via third-party frameworks such as Monorail (http://www.castleproject.org/monorail/index.html).

Recently, Microsoft released the ASP.Net MVC framework to give web developers the option of using this design pattern without the need for a lot of “plumbing” code or the use of a third-party framework.

The Model-View-Controller design pattern splits an application into three distinct parts called (you guessed it) “Models”, “Views” and “Controllers”. 

A Model represents the stateful data in an application.  These are often represented as objects such as “Customer” and “Employee” that represent an abstract business object.  For persistent data, the Model may save and retrieve data to and from a database.  Public properties of these objects (for example, “LastName” or “HireDate”) represent their state at any give time.  The model objects have no visual representation and no knowledge of how they will be displayed on screen. 

A View is the application’s user interface (UI).  In a web application, this is the web page that the user sees and clicks and interacts with directly.  The View can display data but it has no knowledge of where the data it displays comes from.

A Controller is the brains of your application.  It links the Model to the View.  It handles communication between the other two parts of the application.  It is smart enough to detect when a data needs to be retrieved (from the model) and refreshed (in the view).  It sends updated data from the view back to the model so that the model can persist it. 

Below is Trygve M. H. Reenskaug’s diagram of the relationship between these thee parts.

    Figure 1

This separation of the various concerns of the application encourages developers to create loosely-coupled components.

Much of the communication to the controller occurs by raising events in the view, which keeps the controller loosely coupled from the other parts.  However the real advantage of the MVC pattern is that, because they only communicate through the controller, the model and view are very loosely coupled.  This provides the following advantages to an MVC application.

  • Loosely-coupled applications have fewer dependencies, making it easier to switch the user interface or backend at a later time.
  • Applications can be tested more easily, because so little code is in the view.  We can test our code by writing unit tests against the controller.

In the next article, we will look at how to create a Microsoft ASP.Net MVC application.

.Net | ASP.NET | MVC
Sunday, August 17, 2008 2:03:21 PM (GMT Daylight Time, UTC+01:00)
# Saturday, August 16, 2008