Я не запускал его, но я вполне уверен, что это должно сработать!На самом деле единственная действительно общая часть - это контроллер.Другое дело просто обычный полиморфизм.И спасибо за вдохновение.Было весело думать о таком решении.Может быть, я построю нечто подобное в будущем.
Предостережение: вы будете привязывать имя ваших контроллеров к названию каждой модели.Просто знайте об этом!Существует схема именования, которую необходимо сохранить, иначе вы ее нарушите.открытый класс [ModelName] Контроллер: MasterController {}Конечные точки ajax будут заканчиваться значением [PluralName] (Читайте дальше, чтобы узнать, что я имею в виду.)
Вам понадобится дополнительное свойство в MasterTemplate.Идеально сделать его абстрактным, чтобы вы не забыли реализовать его в производных классах.Это для множественного имени в заголовке представления и вызова ajax в представлении.
public abstract class MasterTemplate
{
[Key]
public int Id { get; set; }
public abstract string PluralName {get;}
[Required]
[StringLength(255)]
public string Description { get; set; }
public DateTime? UpdatedOn { get; set; }
public string UpdatedBy { get; set; }
}
Тогда отрасль будет выглядеть так:
public class Industry: MasterTemplate
{
public override string PluralName => "Industries"
}
Создайте действительно универсальный контроллер и получите вседругие контроллеры из него, такие как
public class IndustryController : MasterController<Industry>
{
//done everthing else is in the master :)
}
А вот универсальный MasterController .
public class MasterController<T> : Controller where T : MasterTemplate, new()
{
private ApplicationDbContext _context { get; set; }
private string UserId { get; set; }
public MasterController()
{
_context = new ApplicationDbContext();
UserId = System.Web.HttpContext.Current.User.Identity.GetUserId();
}
public ActionResult Index(int id = 0)
{
T data = (id > 0)
? data = _context.Set<T>().SingleOrDefault(c => c.Id == id) ?? new T()
: new T();
return View("View", data);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(T data)
{
if (!ModelState.IsValid)
return View("View", data);
var record = _context.Set<T>().Where(c => c.Description.Trim().ToLowerInvariant() == data.Description.Trim().ToLowerInvariant() && c.Id != data.Id);
if (record.Count() > 0)
{
ModelState.AddModelError($"Duplicate {typeof(T).Name}", $"{typeof(T).Name} already exist");
return View("View", data);
}
if (data.Id >= 1)
{
T cm = _context.Set<T>().SingleOrDefault(c => c.Id == data.Id);
cm.Description = data.Description;
cm.UpdatedOn = DateTime.Now;
cm.UpdatedBy = UserId;
}
else
{
_context.Set<T>().Add(data);
}
_context.SaveChanges();
return RedirectToAction("Index", new { id = 0 });
}
Назовите представление «Представление» (или точно так же, как вы называете его вMasterController) и поместите его в общую папку, чтобы каждый контроллер мог найти его там.
@model MasterTemplate
@{
string name = Model.GetType().Name;
ViewBag.Title = name;
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h3>@Model.PluralName Management</h3>
<div class="row">
<div class="col-md-4">
@using (@Html.BeginForm("Save", name))
{
@Html.ValidationSummary("Please correct the following")
@Html.HiddenFor(m => m.Id)
<div class="form-group">
<div>
@Html.LabelFor(m => m.Description)
@Html.TextBoxFor(m => m.Description, new { @class = "form-control", autocomplete = "off" })
@Html.ValidationMessageFor(m => m.Description, $"{name} is required.", new { @class = "text-danger" })
</div>
</div>
@Html.AntiForgeryToken()
<button type="submit" class="btn btn-primary btn-sm">Save</button>
}
</div>
<div class="col-md-8">
<table class="table table-sm" id="mydata">
<thead>
<tr>
<th>
@(name)
</th>
<th>
</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
@section scripts
{
@Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function () {
$("#mydata").DataTable({
ajax: {
url: "/api/get/@(Model.PluralName)",
dataSrc: ""
},
columns: [
{
data: "description"
},
{
data: "id",
render: function (data) {
var url = '@Url.Action("Index", "@(name)", new { id = "__data__" })';
return '<a href="' + url.replace('__data__', data) + '">Edit</a>';
}
}
]
});
});
</script>
}