26 May 2011

MVC Issue Tracker: Part 2

Apologies for the delay: But, I’m back in business now, so we’ll pick up where we left off…
Before we can begin with our Controllers, we need to finish one part of the data model: the Database Context.
Entity Framework makes this easy for us, in MVC3.  First, we add a new connection string
<add name="IssueTrackerDbContext"
         connectionString="Data Source=|DataDirectory|IssueTrackerDb.sdf"
         providerName="System.Data.SqlServerCe.4.0"/>

Then, we add a new folder under our Models folder.  I just called it “Data.”  To this folder, we’ll add two classes: IssueTrackerDbContext is our context class.
public class IssueTrackerDbContext : DbContext
    {
        public DbSet<Issue> Issues { get; set; }
        public DbSet<WorkNote> WorkNotes { get; set; }
        public DbSet<User> Users { get; set; }

        protected override void OnModelCreating
            (DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions
               .Remove<PluralizingTableNameConvention>();
        }
    }

This just sets up our entities for our Controllers.  Now, so that we’ll have data to play with as we make other changes, we add the IssueTrackerInitializer.
protected override void Seed(IssueTrackerDbContext context)
{
var Users = new List<User>
{
new User() 
{
UserName = "Agoodner", 
LastName = "Goodner", 
FirstName = "Allen", 
Password = "dontdothis", 
Role = Role.Administrator
}
};
 
Users.ForEach(u => context.Users.Add(u));
context.SaveChanges();
 
var issues = new List<Issue>
{
new Issue() 
{ 
Title = "Sample", 
Description = "A Samle issue.", 
CreatedBy = 1, 
CreatedDate = DateTime.Now, 
AssignedTo = 1, 
AssignedUser = Users[0] 
}
};
 
issues.ForEach(i => context.Issues.Add(i));
context.SaveChanges();
 
var WorkNotes = new List<WorkNote>
{
new WorkNote() 
{ 
IssueId = 1, 
UserId = 1,
Detail = "A Sample Note on a sample issue.", 
LoggedDate = DateTime.Now, 
AttachedIssue = issues[0]
},
new WorkNote() 
{ 
IssueId = 1, 
UserId = 1,
Detail = "Another Sample Note on a sample issue", 
LoggedDate = DateTime.Now, AttachedIssue = issues[0]
}
};
 
WorkNotes.ForEach(w => context.WorkNotes.Add(w));
 
var wnIssue = context.Issues.Where(i => i.IssueId == 1).Single();
 
WorkNotes.ForEach(w => wnIssue.WorkNotes.Add(w));
 
context.SaveChanges();
}

This will allow us to have some sample data when we first initialize  the application.
Now we can begin on our controllers.  We’ll start with an Issue Controller.  Whereas I skipped [Class]Model naming convention with the Models, I’ll leave the ‘Controler’ portion on our controllers.

CropperCapture[2]
For now, we’ll leave the Controller as we find it, but we will update the views.  First, the Index:
Most of our changes are cosmetic: Thus:
@model IEnumerable<MvcIssueTracker.Models.Issue>

@{
    ViewBag.Title = "Index";
}

<h2>Open Issues</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Title
        </th>
        <th>
            Detailed Description
        </th>
        <th>
            Created By
        </th>
        <th>
            Created Date
        </th>
        <th>
            Assigned To
        </th>
        <th>
            Last Updated Date
        </th>
        <th>
            Closed By
        </th>
        <th>
            Closed Date
        </th>
        <th></th>
    </tr>
We changed the <h2> heading to “Open Issues” and we modified the column header names so they look a little more friendly.
The only thing of substance we did was to make the view aware of if an issue is closed or not:
@foreach (var item in Model) {
    if (item.ClosedDate == null)
    { 
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.CreatedBy)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.CreatedDate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.AssignedTo)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastUpdatedDate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ClosedBy)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ClosedDate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id = item.IssueId }) |
            @Html.ActionLink("Details", "Details", new { id = item.IssueId }) |
            @Html.ActionLink("Delete", "Delete", new { id = item.IssueId })
        </td>
    </tr>
    }
Now, with the controller and view in place, we run the app and navigate to /Issue…
CropperCapture[3]
Similar work to the User Controller generates:
CropperCapture[4]
And with the WorkNote Controller produces:
CropperCapture[5]
We’ll stop there, for now.  Between this post and next, I’ll clean up those views, and hook up the Issue to the WorkNotes…

No comments:

Post a Comment