Sunday, June 20, 2010

SubSonic CRUD Controller for ASP.NET MVC

I'm using SubSonic in my projects quite often because of migrations and the code first approach of Simple Repository. To make my (ASP.NET MVC 2) life easier I decided to create a simple controller base class to get CRUD functionality out of the box. To use the AbstractCrudController for a model you will need to derive from AbstractCrudController supply a SimpleRepository instance to the constructor and scaffold your views via VS templates.

The source code can be found on Github.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SubSonic.Repository;
using System.Web.Mvc;
using System.Linq.Expressions;

namespace SubSonic.Contrib.Web
{
    public abstract class AbstractCrudController<T> : Controller where T : class, new()
    {
        protected IRepository Repository { get; private set; }

  protected virtual Expression<Func<T, bool>> FilterIndex { get; set; }

        public AbstractCrudController(IRepository repo)
        {
            Repository = repo;
        }

        public virtual ActionResult Index()
        {
            var model = Repository.All<T>();
            
            if (FilterIndex != null)
            {
                model = model.Where(FilterIndex);
            }

            return View(model);
        }

        public virtual ActionResult Details(int id)
        {
            var model = Repository.Single<T>(id);

            return View(model);
        }

        public virtual ActionResult Create()
        {
            return View();
        } 

        [HttpPost]
        public virtual ActionResult Create(T entity)
        {

            if (!ModelState.IsValid)
            {
                return View();
            }

            try
            {
                Repository.Add(entity);

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
        
        public virtual ActionResult Edit(int id)
        {
            var model = Repository.Single<T>(id);

            return View(model);
        }

        [HttpPost]
        public virtual ActionResult Edit(int id, T entity)
        {
            if (!ModelState.IsValid)
            {
                return View();
            }

            try
            {
                Repository.Update<T>(entity);
 
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        public virtual ActionResult Delete(int id)
        {
            var model = Repository.Single<T>(id);
            
            return View(model);
        }

        [HttpPost]
        public virtual ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                var model = Repository.Delete<T>(id);
            
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
    }
}