title: Generic View and Controller to avoid Duplicate Code in MVC
body: <p>I have lots of models with same basic structure in my MVC project. So, I created a master class like below.</p>
  
  <pre><code>    public class MasterTemplate
      {
          [Key]
          public int Id { get; set; }
  
          [Required]
          [StringLength(255)]
          public string Description { get; set; }
          public DateTime? UpdatedOn { get; set; }
          public string UpdatedBy { get; set; }
      }
  </code></pre>
  
  <p>And I created all my model classes like below.</p>
  
  <pre><code>    public class Industry : MasterTemplate
      {
  
      }
  
      public class Caste : MasterTemplate
      {
  
      }
  
      public class Gender : MasterTemplate
      {
  
      }
  
      public class Qualification : MasterTemplate
      {
  
      }
  
      public class BloodGroup: MasterTemplate
      {
  
      }
  
  </code></pre>
  
  <p>There are many more like this. Following is my code for IndustryController.</p>
  
  <pre><code> public class IndustryController : Controller
      {
          private ApplicationDbContext _context { get; set; }
          private string UserId { get; set; }
  
          public IndustryController()
          {
              _context = new ApplicationDbContext();
              UserId = System.Web.HttpContext.Current.User.Identity.GetUserId();
          }
  
  
          public ActionResult Index(int id = 0)
          {
              Industry data = new Industry();
              if (id &gt; 0)
                  data = _context.Industries.SingleOrDefault(c =&gt; c.Id == id);
              if (data == null)
                  data = new Industry();
  
              return View("Industry", data);
          }
  
          [HttpPost]
          [ValidateAntiForgeryToken]
          public ActionResult Save(Industry data)
          {
              if (!ModelState.IsValid)
                  return View("Industry", data);
  
              var record = _context.Industries.Where(c =&gt; c.Description.Trim().ToLower() == data.Description.Trim().ToLower() &amp;&amp; c.Id != data.Id);
              if (record.Count() &gt; 0)
              {
                  ModelState.AddModelError("Duplicate Industry", "Industry already exist");
                  return View("Industry", data);
              }
  
              Industry cm = new Industry();
              if (data.Id &gt;= 1)
              {
                  cm = _context.Industries.SingleOrDefault(c =&gt; c.Id == data.Id);
                  cm.Description = data.Description;
                  cm.UpdatedOn = DateTime.Now;
                  cm.UpdatedBy = UserId;
              }
              else
              {
                  cm = data;
                  _context.Industries.Add(cm);
              }
              _context.SaveChanges();
  
  
              return RedirectToAction("Index", new { id = 0 });
  
          }
  </code></pre>
  
  <p>And following is my code for IndustryView</p>
  
  <pre><code>@model Industry
  @{
      ViewBag.Title = "Industries";
      Layout = "~/Views/Shared/_Layout.cshtml";
  }
  
  &lt;h3&gt;Industries Management&lt;/h3&gt;
  &lt;div class="row"&gt;
      &lt;div class="col-md-4"&gt;
          @using (@Html.BeginForm("Save", "Industry"))
          {
              @Html.ValidationSummary("Please correct the following")
              @Html.HiddenFor(m =&gt; m.Id)
  
              &lt;div class="form-group"&gt;
                  &lt;div&gt;
                      @Html.LabelFor(m =&gt; m.Description)
                      @Html.TextBoxFor(m =&gt; m.Description, new { @class = "form-control", autocomplete = "off" })
                      @Html.ValidationMessageFor(m =&gt; m.Description)
                  &lt;/div&gt;
              &lt;/div&gt;
              @Html.AntiForgeryToken()
              &lt;button type="submit" class="btn btn-primary btn-sm"&gt;Save&lt;/button&gt;
          }
      &lt;/div&gt;
      &lt;div class="col-md-8"&gt;
          &lt;table class="table table-sm" id="mydata"&gt;
              &lt;thead&gt;
                  &lt;tr&gt;
                      &lt;th&gt;
                          Industries
                      &lt;/th&gt;
                      &lt;th&gt;
  
                      &lt;/th&gt;
                  &lt;/tr&gt;
              &lt;/thead&gt;
              &lt;tbody&gt;&lt;/tbody&gt;
          &lt;/table&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  
  
  @section scripts
  {
      @Scripts.Render("~/bundles/jqueryval")
      &lt;script&gt;
          $(document).ready(function () {
              $("#mydata").DataTable({
                  ajax: {
                      url: "/api/get/industries",
                      dataSrc: ""
                  },
                  columns: [
                      {
                          data: "description"
                      },
                      {
                          data: "id",
                          render: function (data) {
                              var url = '@Url.Action("Index", "Industry", new { id = "__data__" })';
                              return '&lt;a href="' + url.replace('__data__', data) + '"&gt;Edit&lt;/a&gt;';
                          }
                      }
                  ]
              });
          });
      &lt;/script&gt;
  }
  
  </code></pre>
  
  <p>Now my problem is, code for controller and views for all the models in my project is almost similar. It is as above. So, I wanted to generalize them and create a single controller and view which can be used for all my other models. I am new to generics, tried the following code, but still not able to figure out the way forward. It is so confusing for me.</p>
  
  <pre><code>    public interface IMaster
      {
          int Id { get; set; }
          string Description { get; set; }
      }
  
   public class GenericController : Controller
      {
          private ApplicationDbContext _context { get; set; }
          private string UserId { get; set; }
  
          public GenericController()
          {
              _context = new ApplicationDbContext();
              UserId = System.Web.HttpContext.Current.User.Identity.GetUserId();
          }
  
  
          public ActionResult Index(int id = 0)
          {
              IMaster data = null;
              if (id &gt; 0)
                  data = _context.Industries.SingleOrDefault(c =&gt; c.Id == id);
              if (data == null)
                  data = new Industry();
  
              return View("Generic", data);
          }
  
          [HttpPost]
          [ValidateAntiForgeryToken]
          public ActionResult Save(IMaster data)
          {
              if (!ModelState.IsValid)
                  return View("Generic", data);
  
              var record = _context.Industries.Where(c =&gt; c.Description.Trim().ToLower() == data.Description.Trim().ToLower() &amp;&amp; c.Id != data.Id);
              if (record.Count() &gt; 0)
              {
                  ModelState.AddModelError("Duplicate Industry", "Industry already exist");
                  return View("Generic", data);
              }
  
              Industry cm = new Industry();
              if (data.Id &gt;= 1)
              {
                  cm = _context.Industries.SingleOrDefault(c =&gt; c.Id == data.Id);
                  cm.Description = data.Description;
                  cm.UpdatedOn = DateTime.Now;
                  cm.UpdatedBy = UserId;
              }
              else
              {
                  cm.Id = data.Id;
                  cm.Description = data.Description;
                  _context.Industries.Add(cm);
              }
              _context.SaveChanges();
  
  
              return RedirectToAction("Index", new { id = 0 });
  
          }
      }
  </code></pre>
  
  <p>Can somebody guide me in right direction, need to create a generic controller and view for all the similar models in my project.</p>