为了账号安全,请及时绑定邮箱和手机立即绑定

避免MVC中重复代码的通用视图和控制器

避免MVC中重复代码的通用视图和控制器

C#
达令说 2022-11-21 20:45:01
在我的MVC项目中,我有很多具有相同基本结构的模型。所以,我创建了一个像下面这样的大师班。    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; }    }我创建了如下所有的模型类。    public class Industry : MasterTemplate    {    }    public class Caste : MasterTemplate    {    }    public class Gender : MasterTemplate    {    }    public class Qualification : MasterTemplate    {    }    public class BloodGroup: MasterTemplate    {    }像这样的还有很多。下面是我的IndustryController代码。 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 > 0)                data = _context.Industries.SingleOrDefault(c => 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 => c.Description.Trim().ToLower() == data.Description.Trim().ToLower() && c.Id != data.Id);            if (record.Count() > 0)            {                ModelState.AddModelError("Duplicate Industry", "Industry already exist");                return View("Industry", data);            }
查看完整描述

1 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

我还没有运行它,但我很有信心,这应该做的伎俩!实际上,唯一真正通用的部分是控制器。另一个就是常见的多态性。谢谢你的启发。想到这样的解决办法,真是有趣。也许将来我也会造类似的东西。


提醒一句:您将把控制器的名称绑定到每个Model的名称。只是要注意这一点!必须保留一个命名架构,否则会破坏它。


公共类[模型名称]控制器:主控制器<型号Name>

{

}


阿贾克斯端点将以[PluralName]的值结束

(请继续阅读《观点》,了解我的意思。)


您将需要在MasterTemplate中添加一个属性。理想情况下使其抽象,这样您就不会忘记在派生类中实现它。这适用于视图头中的复数名称和视图中的阿贾克斯调用。


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"

}

创建一个真正通用的Controller,并从它派生所有其他Controller,如


public class IndustryController : MasterController<Industry>

{

   //done everthing else is in the master :)

}

这里是通用的MasterController< T>。


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 });


    }

将视图命名为“View”(或与您在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>

}




查看完整回答
反对 回复 2022-11-21
  • 1 回答
  • 0 关注
  • 71 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信