MVC Abstract Base Controller Override parameter type for modelbinding
For simplicity's sake, lets say I have the following Abstract Base Controller Class:
public abstract class RESTControll开发者_如何学编程er : Controller
{
public abstract JsonResult List();
public abstract JsonResult Get(Guid id);
public abstract JsonResult Create(object obj);
public abstract JsonResult Update(object obj);
public abstract JsonResult Delete(Guid Id);
}
For the Create & Update methods, I not only want to override the Method, but also the type of the parameter.
Typically I would use generics like so:
public abstract JsonResult Create<T>(T obj);
However this is an MVC action, and there is no way to specify type parameters.
What are my options? If I leave it as (object obj)
will the MVC model binder work correctly?
var model = obj as MyViewModel;
This isn't very clean in any case. Any help would be appreciated.
How about something among the lines:
public abstract class RESTController<T> : Controller
{
public abstract JsonResult List();
public abstract JsonResult Get(Guid id);
public abstract JsonResult Create(T obj);
public abstract JsonResult Update(T obj);
public abstract JsonResult Delete(Guid Id);
}
and when overriding:
public FooController: RESTController<Foo>
{
...
public override JsonResult Create(Foo obj)
{
throw new NotImplementedException();
}
...
}
If you want something a bit more fleshed out, you could try using something along the lines of the following. I'm using Onion Architecture and Repository Pattern, with IoC, and DI. IEntity
simply provides access to the Id field of the entity (I'm assuming Entity Framework Code First here, with Entity.Id
as the primary key for each entity, whereas EntityId
would designate a foreign key on another table.).
The actions are virtual to allow derived classes to override them where necessary, and the repository is set to protected, so that the derived class can also pull from the repository for the entity. This works with a basic CRUD repository, but could be replaced with an aggregate to allow more functionality.
using System;
using System.Web.Mvc;
using MySolution.Core.Interfaces.EntityFramework;
using MySolution.Core.Interfaces.Repositories;
namespace MySolution.Ux.Web.Site.Primitives
{
/// <summary>
/// Provides mechanisms for performing CRUD operations on entities within a RESTful environment.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
public abstract class CrudController<TEntity> : Controller
where TEntity : class, IEntity, new()
{
/// <summary>
/// The repository to use for CRUD operations on the entity. Derived classes
/// also have access to this repository so that the virtual actions can be
/// overridden with custom implementations.
/// </summary>
protected readonly IRepository<TEntity> Repository;
/// <summary>
/// Initialises a new instance of the <see cref="CrudController{TEntity}"/> class.
/// </summary>
/// <param name="repository">The repository.</param>
protected CrudController(IRepository<TEntity> repository)
{
// Instantiate the controller's repository.
Repository = repository;
}
/// <summary>
/// Lists this specified entities within the data store.
/// </summary>
/// <returns>A JSON formatted list of the entities retrieved.</returns>
[HttpGet]
public virtual JsonResult List()
{
try
{
return Json(Repository.GetAll(), JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
return Json(e.Message, JsonRequestBehavior.AllowGet);
}
}
/// <summary>
/// Gets a specific entity within the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity retrieved.</returns>
[HttpGet]
public virtual JsonResult Get(Guid id)
{
try
{
return Json(Repository.Get(id), JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message, JsonRequestBehavior.AllowGet);
}
}
/// <summary>
/// Creates a specific entity within the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity created.</returns>
[HttpPost]
public virtual JsonResult Create(TEntity entity)
{
try
{
Repository.Add(entity);
Repository.Save();
return Json(entity);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message);
}
}
/// <summary>
/// Updates a specific entity within the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity updated.</returns>
[HttpPut]
public virtual JsonResult Update(TEntity entity)
{
try
{
Repository.Update(entity);
Repository.Save();
return Json(entity);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message);
}
}
/// <summary>
/// Deletes a specific entity from the data store.
/// </summary>
/// <returns>A JSON formatted version of the entity deleted.</returns>
[HttpDelete]
public virtual JsonResult Delete(Guid id)
{
try
{
var entity = Repository.Get(id);
Repository.Remove(entity);
Repository.Save();
return Json(entity);
}
catch (Exception e)
{
// An error has occured. Handle the exceptions as needed and return feedback via JSON.
return Json(e.Message);
}
}
}
}
精彩评论