I made a promise that I’d put up a detailed overview of what I discussed and built today before the end of the day, so let’s see if I can keep my word and get this post out before midnight.  Let’s get started!

As I mentioned in the talk, to get started developing ASP.Net MVC applications you’ll need to to have two things installed, Visual Studio 2008 and the latest version of the MVC Framework.  In order to get started with implementing the application the talk, you’re going to need to have a SQL Server database available.  One very cool thing I didn’t mention during the talk is that along with the MVC Framework being 100% free, it also works quite well with both the free version of Visual Studio 2008 ( Express ), and the free version of SQL Express 2008 ( also denoted ‘Express’ ).

You can download the complete project solution here

**Note**  If you use the solution file, you’ll still need to create a database with the blog table, and you’ll also need to change the web.config connection string to point to your database.

Creating the Project

The first order of business we’ll want to take care of is actually creating the MVC projects, which we achieve by adding a new project of the type ‘ASP.Net MVC Web Application’ from inside the Visual Studio add project screen:

 New MVC Project

We’ll be calling ours ‘CodeCampBlogger2009’, so enter that in and click on OK to get on to the next screen, the ‘Create Unit Test Project’:

image

As I mentioned in the talk, making a test project is really up to your development methodology.  Some folks are die-hard Test-Driven-Development fan, and some aren’t.  What’s great about the MVC framework is that it really lends itself well to Test Driven Development, but you don’t lose any features of the framework if you choose not to develop using TDD.

I’m opting to skip creating a Test Project in order to keep this more of an intro to MVC, so just select the ‘No…’ option and click OK. 

After the dialog, the project will be created for you and you’ll have the skeleton of a full-fledged MVC application:

image

While the skeleton created is actually a working application ( feel free to run it to check it out ), we’re going to delete the items created and start from scratch.  So go ahead and delete the items under the Controller, the Account & Shared folders from under Views, and also the Error.aspx & LogOnUserControl.ascx from under the Views/Shared folder:

image

Open up the Site.Master file and strip out all of the pre-canned HTML and turn it into something that looks like the following:

image

And now we’ve got a clean slate to start building the sample app!

Creating The Database

Let’s again start by building our database up, so add a new database server through Visual Studio:

image

After clicking OK, navigate the connection to the Tables Node and add a new table with the following:

image

Save the table as ‘Blog’ ( I find it easiest to just close the window and have it prompt you to save changes ), and we’ll now be ready to create our Entity Model for access to the database:

image

Create a folder called ‘Data’ in the root of the project, and then right-click, Add Item, and select ADO.NET Entity Data Model.  You can name the file anything you’d like, I chose ‘CodeCampBlogger2009Entities.edmx’:

image

The next screen after clicking ‘Add’ will bring you to the ‘Choose Model Contents’ screen where you can decide to either generate a model based upon an existing database, or create a new empty model.  We want to generate our model based upon our Blog data we just created, so go and select ‘Generate from database’ and click Next.

The next screen you’ll encounter will be the Choose Data Connection dialog, which will prompt you for which data connection you’d like to use.  Go ahead and select the connection you created in the database creation step above, and check the option to include sensitive data in the connection string ( not what you want to do on a production machine! ):

image

Make sure the entity connection settings in Web.config is checked, and then click Next.

The next dialog of the wizard will pop up, and it’s the dialog that will access your data connection and look for tables, views, and procedures to model.  Since we have only one table we’re going to be generating, go ahead and check the tables checkbox and click finish:

image

After a few moments, the wizard will have created out entity model, and we’ll now be ready to start adding in our MVC components.

Adding The Models

We’ll be needing two models for our sample application, one for holding a blog entry, and one to hold all blog entries and also to house our data calls to the entity framework.

Add two classes to the Models directory, one called BlogEntry.cs, and one called BlogData.cs. 

For the BlogEntry class, we’ll want it to be defined as follows:

public class BlogEntry
{
    public int BlogID { get; set; }
    public DateTime Posted { get; set; }
    public string PostedBy { get; set; }
    public string Text { get; set; }
    public string Title { get; set; }
}

And for BlogData, we’ll want it to look like this:

public class BlogData
{
    // Public property to return all blog entries inside of our strongly-typed views
    public BlogEntry[] AllBlogEntries
    {
        get { return GetBlogEntries(); }
    }

    // If we need to persist a BlogEntry across multiple post-backs ( say for instance validation 
    // fails and we want the user to fix an issue ), we'll need space in the model to hold the 
    // current object being worked with
    public BlogEntry BlogEntry
    {
        get;
        private set;
    }

    public BlogData()
        : this(new BlogEntry())
    {

    }

    public BlogData(BlogEntry blogEntry)
    {
        this.BlogEntry = blogEntry;
    }

    // We'll use a simple linq query to pull all blog entries out of the database and return them 
    // instances of our custom blog entry class
    public static BlogEntry[] GetBlogEntries()
    {
        using (Data.CodeCampBlogger2009Entities entities = new Data.CodeCampBlogger2009Entities())
        {
            var allBlogEntries = from blog in entities.Blog
                                 orderby blog.Posted descending
                                 select new BlogEntry() { 
                                     BlogID = blog.BlogID, 
                                     Posted = blog.Posted, 
                                     PostedBy = blog.PostedBy, 
                                     Text = blog.Text, 
                                     Title = blog.Title };

            return allBlogEntries.ToArray();
        }
    }

    // Inserts will be as simple as possible, we'll take our custom class and cram the data into a Blog Entity 
    // and save it to the database
    public static void InsertBlogEntry(BlogEntry newBlogEntry)
    {
        using (Data.CodeCampBlogger2009Entities entities = new Data.CodeCampBlogger2009Entities())
        {

            newBlogEntry.Posted = DateTime.Now;

            var blogEntry = new Data.Blog() { 
                Posted = newBlogEntry.Posted, 
                PostedBy = newBlogEntry.PostedBy, 
                Text = newBlogEntry.Text, 
                Title = newBlogEntry.Title };

            entities.AddToBlog(blogEntry);
            entities.SaveChanges();
        }
    }
}
 
And that’s all we’ll need to do with our models, and we can move on to the next piece of the application.
 
Adding The Controller
 
Right-click on the Controllers directory and select ‘Add Controller’ from the menu.  You’ll be prompted to name your controller, I called mine ‘BlogController’ and clicked ‘Add’:
 
image
 
Once you’ve got your BlogController class up and open, we’ll want to changed the class to have the two action methods we’ll need for our applciation, the ‘Index’ action and the ‘AddBlogEntry’ action:
 
public class BlogController : Controller
{
    public ActionResult Index()
    {
        return View(new BlogData());
    }

    public ActionResult AddBlogEntry(BlogEntry blogEntry)
    {
        blogEntry.Posted = DateTime.Now;

        BlogData.InsertBlogEntry(blogEntry);

        return View("Blog", new BlogData());
    }
}
 
For the Index action, I’d like to reiterate what I talked about during the presentation, and that is the fact that the MVC framework will infer the View name for you automatically if you do not specify a view name when calling the View method on the controller.  What happens in that case is that the framework will take a look at the current action ( in our case, Index ), and search for a view named Index in the default view paths ( /Views/{Controller Name}/{ViewName}  and /Views/Shared/{ViewName} ).  If it doesn’t find one, it’ll throw an exception.
 
In the talk, I started this controller with a regular post-back, and you might remember that instead of returning the View named ‘Blog’ in the AddBlogEntry Action, I was instead re-directing back to the Index method.  I’m going to skip the regular post-back here and just make our controller hand back what we’ll be needing for the Ajax functionality, and that is a partial-view that contains the blog entries and the blog form.
 
Adding The Views
 
We need two views to complete the sample application, so let’s go ahead and create them.  For the ‘Index’ view,  click anywhere within the Index action and select ‘Add View’:
 
image
 
We want this view to be our base page that shows all the content and submission form, so we’d like to have it use the Master page, and be strongly-typed to our BlogData model.  Go ahead and click ‘Add’ and have it create the view.
 
If you look at what happens when you click ‘Add’, you’ll see that Visual Studio creates a sub-folder under views named ‘Blog’, and adds our view to that directory.  Had we not initiated adding our view by clicking inside the Index action method, we' would have had to manually create the Blog folder and add the view directly to that folder.
 
Our new Index view should be filled out with the following HTML:
 
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Code Camp Blogger 2009
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Code Camp Blogger 2009</h2>
    
    <div id="blogData">
        <% Html.RenderPartial("Blog"); %>
    </div>

</asp:Content>

Note that we’re wrapping the partial view inside of a named div so that when we return the results of adding a blog post via ajax, we can replace what’s inside the div with what’s returned to us from the action ajax calls.

Now we’ll add our ‘Blog’ partial-view, but this time we’ll need to add it into our Blog sub-folder by right clicking and selecting Add –> View. This view will be rendered as a component of another view, so we’ll need to check ‘Create a partial view’ and skip selecting a master page ( it’ll be disabled while partial view is checked ).  Don’t forget to strongly type our view to our BlogData model:

image

Once we’ve go the ‘Blog’ partial-view created, we’ll want to add in the following HTML:

<table>
    <tr>
        <td style="vertical-align: top; width: 50%;">
            <fieldset>
                <legend><span style="font-weight: bold;">Entries:</span> </legend>
                <% foreach (CodeCampBlogger2009.Models.BlogEntry blogEntry in this.Model.AllBlogEntries)
                    { %>
                <h4>
                    <%= blogEntry.Title %></h4>
                <%= blogEntry.Text %>
                <h5>
                    Posted By
                    <%= blogEntry.PostedBy %>
                    @
                    <%= blogEntry.Posted.ToShortDateString() %>
                    <%= blogEntry.Posted.ToShortTimeString() %></h5>
                <hr />
                <% } %>
                
                <% if (this.Model.AllBlogEntries.Length == 0)
                    { %>
                    No Current Blog Entries
                <% } %>
            </fieldset>
        </td>
        <td style="vertical-align: top; width: 50%;">
            <fieldset>
                <legend><span style="font-weight: bold;">Add Post:</span> </legend>
                <% using ( Ajax.BeginForm("AddBlogEntry", "Blog",
new AjaxOptions() { UpdateTargetId = "blogData" }) ) { %> <table> <tr> <td style="vertical-align: top;"> Title: </td> <td> <%= Html.TextBox("Title") %> </td> </tr> <tr> <td style="vertical-align: top;"> Posted By: </td> <td> <%= Html.TextBox("PostedBy") %> </td> </tr> <tr> <td style="vertical-align: top;"> Text: </td> <td> <%= Html.TextArea("Text", new { rows = 8, cols = 40 }) %> </td> </tr> <tr> <td colspan="2" style="text-align: right;"> <input type="submit" value="Add Post" /> </td> </tr> </table> <% } %> </fieldset> </td> </tr> </table>

And that’s it for the views!

Adding Ajax Scripts And A Default Route

For Ajax functionality, we’ll need to add in the MVC javascript includes ( they’re left out of the master page header section by default on a new project ).  Open up the Site.Master file and add the following two script includes to the head section of the document:

<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>" type="text/javascript"></script>
                                    

One last thing we’ll need to do before we run our application is change the default route to point to our new BlogController and not the HomeController it’s set to when the project is first created.  To change the default route, open up the Global.asax.cs file in the root of the project, and change the ‘routes.MapRoute(…..’ method to be:

routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Blog", action = "Index", id = "" }  // Parameter defaults
            );

After making the last few changes above, we’re finished with our sample MVC application and we can see it in action.

The Final Result

If we now run the application, we’ll be able to see the results of all the work we’ve done up to this point.

Initial Page Load:

image

After a few posts:

image

 

A Few Thoughts

While the sample application implements the very core components of an MVC framework application, there are two pieces missing that are keeping it form being what I consider a proper demo application.  These missing components are Data Validation & Security, both of which are provided by the core MVC framework runtime. I’ll be covering these topics here on the blog in the coming weeks, so check back later on to see how I’ll be implementing them in this application.

And that’s it for recapping today’s presentation!

- Colin