Skip to content

Instantly share code, notes, and snippets.

@dkellycollins
Last active August 24, 2016 21:44
Show Gist options
  • Save dkellycollins/6074963 to your computer and use it in GitHub Desktop.
Save dkellycollins/6074963 to your computer and use it in GitHub Desktop.
A generic model controller for ASP.NET MVC framework.
@using BootstrapSupport
@model Object
<div class="container">
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset class="form-horizontal">
<legend>@Model.GetLabel() <small>Details</small></legend>
@foreach (var property in Model.VisibleProperties())
{
using(Html.ControlGroupFor(property.Name)){
@Html.Label(property.Name.ToSeparatedWords(), new { @class = "control-label" })
<div class="controls">
@Html.Editor(property.Name, new { @class = "input-xlarge" })
@Html.ValidationMessage(property.Name, null, new { @class = "help-inline" })
</div>
}
}
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save changes</button>
@Html.ActionLink("Cancel", "Index", null, new { @class = "btn " })
</div>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
</div>
@using BootstrapSupport
@model Object
<div class="container">
<fieldset>
<legend>@Model.GetLabel() <small>Details</small></legend>
<dl> <!-- use this class on the dl if you want horizontal styling http://twitter.github.com/bootstrap/base-css.html#typography class="dl-horizontal"-->
@foreach(var property in Model.VisibleProperties())
{
<dt>
@property.GetLabel().ToSeparatedWords()
</dt>
<dd>
@Html.Display(property.Name)
</dd>
}
</dl>
</fieldset>
<p>
@Html.ActionLink("Edit", "Edit", Model.GetIdValue()) |
@Html.ActionLink("Back to List", "Index")
</p>
</div>
@using BootstrapSupport
@model System.Collections.IEnumerable
<div class="container">
<h2>@Model.GetLabel() <small>Listing</small></h2>
<table class="table table-striped">
<caption></caption>
<thead>
<tr>
@foreach (var property in Model.VisibleProperties())
{
<th>
@property.GetLabel().ToSeparatedWords()
</th>
}
<th></th>
</tr>
</thead>
@{ int index = 0; }
@foreach (var model in Model)
{
ViewData[index.ToString()] = model;
<tr>
@foreach (var property in model.VisibleProperties())
{
<td>
@Html.Display(index + "." + property.Name)
</td>
}
<td>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
Action
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
@{
@Html.TryPartial("_actions", model)
var routevalues = model.GetIdValue();
<li>@Html.ActionLink("Edit", "Edit", routevalues)</li>
<li>@Html.ActionLink("Details", "Details", routevalues)</li>
<li class="divider"></li>
<li>@Html.ActionLink("Delete", "Delete", routevalues)</li>
}
</ul>
</div>
</td>
</tr>
index++;
}
</table>
<p>
@Html.ActionLink("Create New", "Create", null, new {@class = "btn"})
</p>
</div>
/// <summary>
/// Defines fields that every model will need to have.
/// </summary>
public class Model
{
/// <summary>
/// The primary id for the model.
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int ID { get; set; }
}
/// <summary>
/// A generic controller for Models. Note that this class cannot be used directly.
/// </summary>
/// <typeparam name="T">The model type</typeparam>
public class ModelController<T> : Controller
where T : Model, new()
{
protected ModelDbContext _context;
protected ModelController()
{
//_context =
}
/// <summary>
/// Gets all models of type T and displays the index view.
/// </summary>
/// <returns></returns>
[HttpGet]
public virtual ActionResult Index()
{
return View(_context.GetAllModels<T>());
}
/// <summary>
/// Attempts to find a model by the id. If one is found returns the details. Otherwise returns HttpNotFound.
/// </summary>
/// <param name="id">Id of the model</param>
/// <returns></returns>
[HttpGet]
public virtual ActionResult Details(int id = 0)
{
T model = _context.GetModel<T>(id);
if (model == null)
{
return HttpNotFound();
}
return View(model);
}
/// <summary>
/// Attemps to create a default instance of the model and return the create view.
/// </summary>
/// <returns></returns>
[HttpGet]
public virtual ActionResult Create()
{
T model = new T();
return View(model);
}
/// <summary>
/// Creates a new model using the data from model.
/// </summary>
/// <param name="model">Model to create.</param>
/// <returns></returns>
[HttpPost]
public virtual ActionResult Create(T model)
{
if (ModelState.IsValid)
{
_context.CreateModel(model);
return RedirectToAction("Index");
}
return View(model);
}
/// <summary>
/// Attempt to find the model using id. If one is found returns the data so it can be edited.
/// </summary>
/// <param name="id">Id for the model.</param>
/// <returns></returns>
[HttpGet]
public virtual ActionResult Edit(int id = 0)
{
T model = _context.GetModel<T>(id);
if (model == null)
{
return HttpNotFound();
}
return View("Create", model);
}
/// <summary>
/// Updates the model using the model provided.
/// </summary>
/// <param name="model">Model with updates.</param>
/// <returns></returns>
[HttpPost]
public virtual ActionResult Edit(T model)
{
if (ModelState.IsValid)
{
_context.UpdateModel(model);
return RedirectToAction("Index");
}
return View("Create", model);
}
/// <summary>
/// Removes the model completely from the database.
/// </summary>
/// <param name="id">Id of the model to remove.</param>
/// <returns></returns>
[HttpGet]
public virtual ActionResult Delete(int id)
{
Model model = _context.GetModel<T>(id);
_context.RemoveModel(model);
return RedirectToAction("Index");
}
}
/// <summary>
/// Extends DbContext to allow listeners to be notified when a model has changed in the database.
/// </summary>
public class ModelDbContext : DbContext
{
public delegate void ModelEventHandler(Model model);
/// <summary>
/// Raised when a model has been created in the database.
/// </summary>
public static event ModelEventHandler ModelCreated = delegate { };
/// <summary>
/// Raised when a model has been updated in the database.
/// </summary>
public static event ModelEventHandler ModelUpdated = delegate { };
/// <summary>
/// Raised when a model has been removed from the datbase.
/// </summary>
public static event ModelEventHandler ModelRemoved = delegate { };
/// <summary>
/// Used for testing purposes only.
/// </summary>
public ModelDbContext()
{ }
public ModelDbContext(string connectionString)
: base(connectionString)
{ }
public ModelDbContext(DbConnection connection)
: base(connection, false)
{ }
/// <summary>
/// Gets a single model from the database.
/// </summary>
/// <typeparam name="T">Type of the model.</typeparam>
/// <param name="modelId">ID of the model.</param>
/// <returns>The model.</returns>
public virtual T GetModel<T>(int modelId)
where T : Model
{
return Set<T>().Find(modelId);
}
/// <summary>
/// Gets all models from the database of type T.
/// </summary>
/// <typeparam name="T">Type of the model.</typeparam>
/// <returns></returns>
public virtual IQueryable<T> GetAllModels<T>()
where T : Model
{
return Set<T>().AsQueryable();
}
/// <summary>
/// Creates a new model in the database.
/// </summary>
/// <param name="model">The model to create.</param>
public virtual void CreateModel(Model model)
{
Set(model.GetType()).Add(model);
SaveChanges();
ModelCreated(model);
}
/// <summary>
/// Updates a model in the database.
/// </summary>
/// <param name="model"></param>
public virtual void UpdateModel(Model model)
{
Entry(model).State = EntityState.Modified;
SaveChanges();
ModelUpdated(model);
}
/// <summary>
/// Removes a model from the database.
/// </summary>
/// <param name="model"></param>
public virtual void RemoveModel(Model model)
{
Set(model.GetType()).Remove(model);
SaveChanges();
ModelRemoved(model);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment