I am working on the Design of an .NET MVC WEB application and have determined that I have to Manage 33 tables (so far). By Manage I mean the typical SQL operations (insert,update,delete and query)
16 out of those 33 tables are reference tables that need to be handled with the typical CRUD aproach. By reference table I mean tables that are reference by other tables and used in combos (ie coutries, states, cities, currencies, etc)
I am very new to MVC in .NET but have seen that when you scaffold you get Controllers that have the typical methods:
Also on the database side I plan to have the typical DAO that using EntityFramework implements the INSERT, UPDATE, DELETE and LIST (query operations)
Here are my questions (finally ;-)
Since 50% of my tables will be managed visually and functionally in the same way and offer the same CRUD operations is there a pattern or approach that I can use that achieves the best possible code/view reuse ? .
What I want to avoid is to scaffolding 16 entities to get 16 controllers each with 16*5 Views (Create, Delete, Details, Edit and Index)
Is it possible to have a Single Main controller
that can route or manage all those 16 entities and calls the entity needed operations ?
Is it possible to have the a single set of Views (Create, Delete, Details, Edit and Index) that are generic enough to handle those same 16 entities ?
If the two above are possible how will I go about wiring the routing in the configuration of the web project to still be able to have specific URLs for each of those 16 entities (/Countries/Edit/5 , /States/Edit/5 and so on) ?
Here is one way that I think I can achieve this:
Please help me validate/complete my very draft design and mention some caveats or better approaches to achieve this.
Just to provide some context here is a link for the approch of scaffolding EntitieFramework entities with MVC project https://code.msdn.microsoft.com/MVC5-Demo-with-Entity-c6bc81df
Here is a very similar question with an accepted answer that I would like to validate before deciding on how to achieve this.
I had similar situation on my previous project. I did it this way. Here is the general interface for every entity(table)
public interface IRepository<T>
{
void Add(T entity, User initiator);
void Update(T entity, User initiator);
void Delete(T entity);
void Delete(int entityId);
IEnumerable<T> GetAll();
T GetById(int entityId);
}
This general data layer can be easily implemented with Entity Framework(code sample for example here at the bottom) or using different approach(stored procedures as in my case)
I actually don't have any additional business logic, so my web project had direct access to data repository. So it is my generic base controller
public abstract class BaseController<T, M> : Controller
where M : new()
{
public BaseController(IRepository<T> repository)
{
this._repository = repository;
ViewBag.CurrentUser = CurrentUser;
}
protected User CurrentUser
{
get
{
if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
return Mapper.Map<User>(System.Web.HttpContext.Current.User.Identity);
}
return null;
}
}
protected virtual int PageSize
{
get { return 5; }
}
protected IRepository<T> _repository;
public virtual ActionResult Index(int? currentPage)
{
var entities = _repository.GetAll();
List<M> model = new List<M>();
foreach (var currentEntity in entities)
{
model.Add(Mapper.Map<M>(currentEntity));
}
int pageNumber = (currentPage ?? 1);
return View(model.ToPagedList(pageNumber, PageSize));
}
[HttpGet]
public virtual ActionResult Add()
{
return View(new M());
}
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public virtual ActionResult Add(M model)
{
if (ModelState.IsValid)
{
_repository.Add(Mapper.Map<T>(model), CurrentUser);
return RedirectToAction("Index");
}
return View(model);
}
[HttpGet]
public virtual ActionResult Update(int modelId)
{
T domainModelEntity = _repository.GetById(modelId);
M model = Mapper.Map<M>(domainModelEntity);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public virtual ActionResult Update(M model)
{
if (ModelState.IsValid)
{
_repository.Update(Mapper.Map<T>(model), CurrentUser);
return RedirectToAction("Index");
}
return View(model);
}
public virtual ActionResult Delete(int modelId)
{
_repository.Delete(modelId);
return RedirectToAction("Index");
}
}
And this specific controller
public class WebPagesController : BaseWebEntityController<WebPage, WebPageModel>
{
public WebPagesController(IRepository<WebPage> repository)
: base(repository)
{
}
}
A little explanation. a)You should use some IOC for controller dependency resolving.b)T is for entity from database(table) and M is for Model which is returned to View.c) Automapper is well known library.
I didn't make any changes to routing. Left it default.
Hope it helps. Good luck.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.