The Quest for the perfect ASP.Net MVC code : Let the games begin

by Tom 3. December 2009 19:41

Edit:

Please note that the source has changed a lot lately, and that I now use a proper viewmodel instead of domain objects, so all hardlinked references to the domain objects & controllers in the MVC project have disappeared. This also automaticly made my ugly domain object extension methods to get the controller action links completely redundant.

You can see the latest version on github.

The next thing to do is split up the mapping bit using a proper mapping tool (f.e. AutoMapper).

Edit 2:

New article here : The Quest for the perfect ASP.Net MVC code : v0.3

// For a while I have been looking for the perfect ASP.Net MVC code.
// This is the cleanest code I have been able to write.
// I would like to challenge everyone to do better !!!
//
// By this I mean creating a better controller/views if possible codewise.
// The focus is not on the layout stuff, but having it might be a plus.
//
// The scope : a very rudimentary Task list (KISS)
//
// Some more info about my approach :
// It uses view models which contain both data and ActionLink references
// (like ICommand in WPF M-V-VM )
//
// You can download the full source here :
//     http://github.com/ToJans/MVCExtensions/tree/master/src/
//
// You will see it is very easy to alter, just download it and press F5
//
// Please do let me know what you think about my approach as well,
// and whether you could do better: ToJans@twitter
// Send this link to as much fellow coders as possible, so we can see lots of alternatives
//
// PS: you can also leave a comment @ my website (look at my twitter account)
//

// --------------------------------------------------------------------------------
// Controller :
// --------------------------------------------------------------------------------
namespace Tasks.Core.Controllers
{
    public class TaskController : Controller
    {
        // for the sake of the demo we do not use DI
        // but just a static class instance here with a fake repo
        static IRepository<Task> rTask = rTask ?? new FakeRepository<Task>(null);

        public ActionResult Index()
        {
            return View(new VMIndex()
            {
                AllTasks = rTask.Find.OrderBy(o => o.Name),
                AL_AddTask = this.ActionLink("Add new task",c=>c.AddNewTask(null,null))
            });
        }

        public ActionResult AddNewTask(string name,string description)
        {
            var t = new Task() { Description = description, Name = name };
            rTask.SaveOrUpdate(t);
            return this.RedirectToAction(c => c.Index());
        }

        public ActionResult Done(int id)
        {
            var t = rTask.GetById(id);
            t.Done = !t.Done;
            rTask.SaveOrUpdate(t);
            return this.RedirectToAction(c=>c.Index());
        }

        public ActionResult Edit(int id)
        {
            var t = rTask.GetById(id);
            return View(new VMEdit()
            {
                 Name = t.Name,
                 Description = t.Description,
                 AL_PostEdit = this.ActionLink("Save changes",c=>c.PostEdit(t.Id,null,null)),
                 AL_CancelEdit = this.ActionLink("Cancel changes",c=>c.Index())
            });
        }

        public ActionResult PostEdit(int id,string name,string description)
        {
            var t = rTask.GetById(id);
            t.Name = name;
            t.Description = description;
            rTask.SaveOrUpdate(t);
            return this.RedirectToAction(c => c.Index());
        }

        public ActionResult Delete(int id)
        {
            rTask.Delete(rTask.GetById(id));
            return this.RedirectToAction(c => c.Index());
        }
    }
}

// --------------------------------------------------------------------------------
// Index.Spark
// --------------------------------------------------------------------------------
<viewdata model="Tasks.Core.ViewModel.Tasks.VMIndex" />
<content name="Title">
    Index
</content>

<content name="Main">
<h1>Task list</h1>
<if condition="Model.AllTasks.Count()==0">
    No tasks yet.
</if>
<else>
  <table>
    <tr>
      <td>Name</td>
      <td>Name</td>
      <td>Status</td>
      <td>Edit</td>
      <td>Delete</td>
    </tr>
    <tr each="var t in Model.AllTasks">
        <td>${t.Name}</td>
        <td>${t.Description}</td>
        <td><alink a="t.AL_Status()" /></td>
        <td><alink a="t.AL_Edit()" /> </td>
        <td><alink a="t.AL_Delete()" /> </td>
    </tr>
  </table>
</else>
<hr />
<h3>Add a new task</h3>
    <aform a="Model.AL_AddTask">
      <label for="Name">Name :</label><br />
      <input type="text" name="Name" /><br />
      <label for="Description">Description:</label><br />
      <textarea cols="20" rows="2" name="Description" ></textarea><br />
    </aform>
</content>

// --------------------------------------------------------------------------------
// Edit.Spark
// --------------------------------------------------------------------------------
<viewdata model="Tasks.Core.ViewModel.Tasks.VMEdit" />

<content name="Title">
    Edit
</content>
<content name="Main">
        <h3>Edit this task</h3>
        <aform a="Model.AL_PostEdit">
            <label for="Name">Name :</label><br/>
            <input type="text" value="${Model.Name}" name="Name" /><br/>
            <label for="Description">Description:</label><br/>
            <textarea cols="20" rows="2" name="Description" >${Model.Description}</textarea><br />
        </aform>
        <alink a="Model.AL_CancelEdit" />
</content>

 

 

Bookmark and Share

Comments

12/7/2009 8:58:47 AM #

trackback

Social comments and analytics for this post

This post was mentioned on Twitter by ToJans: The Quest for the perfect ASP.Net MVC code : Let the games begin http://bit.ly/4pnY2V (please RT)

uberVU - social comments |

About Tom

Tom Janssens op LinkedIn

Tom Janssens op twitter

Core bvba RSS

 

Tom Janssens is an independent freelance ICT consultant that has been "into computers" ever since the age of 7.

Typing source code from a book evolved into exploring the limits of coding in procedural, assembly and object-oriented languages.
As he matured in software coding, he started focussing on the problems surrounding software development, and learned that software development is usually about people and interactions first, and about technology second.

Due to his diverse track record he gained insights in a lot of aspects of the software development process. Currently his main focus is on strategic ICT advice, lean product/project development and improving the software development process and architecture.

He avoids ivory-tower-approaches by applying and verifying the applicability of the latest tech buzz in software experiments.

He is also the founder of the following LinkedIn groups:

CQRS Professional
BDD Professional
Asp.Net MVC professional

More info about Tom and his company...


Advertisement

Forget all your SCRUM -, Kanban - and other Agile and Lean certificates

Here is the only true AGILE and LEAN certificate you will ever need:

The Creative Recursive Analysis Process Certificate
(CRAP Certificate for short)

More info can be found at the official CRAP certificate website:
http://bit.ly/CRAPCertificate