【问题标题】:Avoid redundancy in multiple controllers in C# code避免 C# 代码中多个控制器的冗余
【发布时间】:2020-03-21 21:15:16
【问题描述】:

我正在编写一个将数据插入 6 个不同数据库的应用程序。每个数据库都有其模型、控制器和视图。

问题是它们都具有相同的方法,只是略有不同,但总的来说,它们都是相同的。这是冗余和每个控制器中的许多类似代码。

有没有办法减少这种情况?您是否会建议一种设计模式来研究以在这里实现它,因为我觉得我在这里所做的是一种糟糕的编程实践?

我是正确的还是偏执狂?谢谢

控制器 1:

namespace Manage_account.Controllers
{
    public class HRLoanController : Controller
    {

        private Entities db = new Entities();

        string EmployeeLogin = System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\')[1];

        [HttpGet]
        public ActionResult Create()
        {
            ViewBag.DepID = new SelectList(db.Departments , "DepID", "Department1");
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(AccountVM vM)
        {
            if (ModelState.IsValid)
            {
                #region Insert in account and lob of HRLoan database
                var chk_accountName = db.Accounts.Any(x => x.AccountName == vM.Accountex.Name);
                try
                {
                    if (!chk_accountName)
                    {
                        Account account = new Account();
                        account.AccountName = vM.Accountex.Name;
                        account.IsActive = true;
                        db.Accounts.Add(account);
                        db.SaveChanges();
                        TempData["success"] = "account saved successfully !";

                    }
                    else
                    {
                        TempData["warning"] = "Data already exists";
                    }

                    var Find_AccountId = db.Accounts.Where(x => x.AccountName == vM.Accountex.Name).FirstOrDefault();
                    var theID = Find_AccountId.AccountID;
                    var chk_lobName = db.LOBs.Where(x => x.AccountID == theID).Any(x => x.LOB1 == vM.LOBex.Name);
                    if (!chk_lobName)
                    {
                        LOB oB = new LOB();
                        oB.LOB1 = vM.LOBex.Name;
                        oB.LOBValue = vM.LOBex.Name;
                        oB.IsActive = true;
                        oB.AccountID = theID;
                        oB.DEPID = vM.Accountex.Dep_ID;
                        db.LOBs.Add(oB);
                        db.SaveChanges();
                        TempData["success"] = "lob saved successfully !";
                    }
                    else
                    {
                        TempData["warning"] = "Data already exists";
                    }

                }
                catch
                {
                    TempData["error"] = "Something went wrong :( .Please, try again later.";
                }

                #endregion
            }

            return RedirectToAction("Create");

        }

        public ActionResult CreateLob()
        {
            ViewBag.DepID = new SelectList(db.Departments, "DepID", "Department1");
            ViewBag.AccountID = new SelectList(db.Accounts.OrderBy(x=>x.AccountName), "AccountID" , "AccountName");
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateLob(LOBex lOBex)
        {
            #region insert in Lob table in HRLoan database 
            if (ModelState.IsValid)
            {
                try
                {
                    var chk_LobName = db.LOBs.Where(x => x.AccountID == lOBex.Account_ID).Any(x => x.LOB1 == lOBex.Name);
                    if (!chk_LobName)
                    {
                        LOB oB = new LOB();
                        oB.LOB1 = lOBex.Name;
                        oB.LOBValue = lOBex.Name;
                        oB.IsActive = true;
                        oB.DEPID = lOBex.DEPID;
                        oB.AccountID = lOBex.Account_ID;
                        db.LOBs.Add(oB);
                        db.SaveChanges();
                        TempData["success"] = "Data saved to LOB Table !";
                    }
                    else
                    {
                        TempData["warning"] = "Data already exists !";
                    }

                }
                catch
                {
                    TempData["danger"] = "Something went wrong :(. Please, try again later.";
                }

            }
            return RedirectToAction("CreateLob");
            #endregion

        }

        [HttpGet]
        public ActionResult CreateUser()
        {
            ViewBag.RoleID = new SelectList(db.Roles.OrderBy(x => x.Role1), "RoleID", "Role1");
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateUser(AddUser addUser)
        {
            #region Insert new user in Users table in HRLoan database 
            if (ModelState.IsValid)
            {

                var chk_user_existence = db.Users.Any(x => x.UserID == addUser.UserID); //check if user exists in db or not
                if (!chk_user_existence)
                {
                    User user = new User();
                    user.UserID = addUser.UserID;
                    user.UserName = addUser.UserName;
                    user.UserEmail = addUser.UserEmail;
                    user.IsActive = true;
                    user.InsertedOn = DateTime.Now;
                    user.UpdatedBy = EmployeeLogin;
                    user.GradeID = addUser.GradeID;
                    user.RoleID = addUser.RoleID;
                    db.Users.Add(user);
                    db.SaveChanges();
                }
                else
                {
                    TempData["warning"] = "This user already exists in Users table !";
                }
            }
            else
            {
                TempData["error"] = "Something went wrong :/ . Please, try again later!";
            }

            return RedirectToAction("CreateUser");
            #endregion
        }

        [HttpGet]
        public ActionResult CreateBoss_Department()
        {
            var get_Admin = db.Users.Where(x => x.RoleID == 1).Where(x=>x.IsActive==true).ToList();
            ViewBag.UserID = new SelectList(get_Admin.OrderBy(x=>x.UserName) , "UserID", "UserName");
            ViewBag.Indexs = new SelectList(db.LOBs , "Indexs", "LOB1");
            ViewBag.AccountID = new SelectList(db.Accounts.OrderBy(x=>x.AccountName) , "AccountID", "AccountName");
            return View();
        }

        #region populate user's ID with their specified names 

        //populate user's names
        public JsonResult GetUserName_toUserLogin(string usr)
        {
            List<User> getUser = new List<User>();
            getUser = (from r in db.Users where (r.UserID == usr) select r).ToList();
            List<SelectListItem> User_ID = new List<SelectListItem>();

            foreach (User name in getUser)
            {
                User_ID.Add(new SelectListItem { Text = name.UserID, Value = name.UserName.ToString() });
            }
            return Json(new SelectList(User_ID, "Value", "Text"));

        }
        #endregion

        #region Populates Lobs according to the selected account in the Create boss-department view 
        //populate Lobs
        public JsonResult GetLOB_toAccount(int acc)
        {
            List<LOB> getLob = new List<LOB>();
            getLob = (from r in db.LOBs where (r.AccountID == acc) select r).ToList();
            List<SelectListItem> Lobs = new List<SelectListItem>();

            foreach (LOB lob in getLob)
            {
                Lobs.Add(new SelectListItem {Text = lob.LOB1, Value = lob.Indexs.ToString() });
            }
            return Json(new SelectList(Lobs , "Value" , "Text"));
        }
        #endregion



        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateBoss_Department(Boss_Dep boss_Dep)
        {
            #region Insert new record for admins only in Boss_Deapartment table in HRLoan database 




            if (ModelState.IsValid)
            {
                var Chk_UsrAccess = db.Boss_Department.Where(x => x.BossLogin == boss_Dep.BossLogin).Any(x => x.LOBIndexs == boss_Dep.LOBIndexs);
                if (!Chk_UsrAccess)
                {
                    Boss_Department boss_ = new Boss_Department();
                    boss_.BossLogin = boss_Dep.BossLogin;
                    boss_.LOBIndexs = boss_Dep.LOBIndexs;
                    boss_.IsActive = true;
                    boss_.ToMail = boss_Dep.To_mail;
                    boss_.InsertedOn = DateTime.Now;
                    boss_.UpdatedBy = EmployeeLogin;
                    db.Boss_Department.Add(boss_);
                    db.SaveChanges();
                    TempData["success"] = "Data saved successfully !";
                }
                else
                {
                    TempData["warning"] = "Data already exists in Boss_Department table !";
                }

            }
            else
            {
                TempData["error"] = "something went wrong :( !";
            }

            return RedirectToAction("CreateBoss_Department");
            #endregion

        }





        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

控制器 2:

namespace Manage_account.Controllers
{
    public class HrperonalController : Controller
    {
        private personal personal = new personal();

        string EmployeeLogin = System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\')[1];


        //GET: create
        [HttpGet]
        public ActionResult Create()
        {
            ViewBag.DepID = new SelectList(personal.Departments, "DepID", "Department");
            return View();
        }


        //POST: create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(AccountVM vM)
        {
            if (ModelState.IsValid)
            {
                #region insert account in account table in HRPersonnal db
                var chk_accountName = personal.Accounts.Any(x => x.AccountName == vM.Accountex.Name);
                if (!chk_accountName)
                {
                    Accounts accounts = new Accounts();
                    accounts.AccountName = vM.Accountex.Name;
                    accounts.IsActive = true;
                    personal.Accounts.Add(accounts);
                    personal.SaveChanges();
                    TempData["success"] = "Account has been saved successfully :) !";
                }
                else
                {
                    TempData["warning"] = "account already exists";
                }
                #endregion

                #region insert Lob under that account in LOB table in HRPersonnal db
                var Added_account = personal.Accounts.Where(x=>x.AccountName == vM.Accountex.Name).FirstOrDefault().AccountID;
                var chk_lobName = personal.LOB.Where(x => x.DEPID == vM.LOBex.DEPID)
                    .Where(x => x.AccountID == Added_account).Any(x => x.LOB1 == vM.LOBex.Name);
                if (!chk_lobName)
                {
                    LOB lOB = new LOB();
                    lOB.LOB1 = vM.LOBex.Name;
                    lOB.LOBValue = vM.LOBex.Name;
                    lOB.AccountID = Added_account;
                    lOB.DEPID = vM.LOBex.DEPID;
                    lOB.IsActive = true;
                    personal.LOB.Add(lOB);
                    personal.SaveChanges();
                    TempData["success"] = "Lob has been saved successfully :) !";
                }
                else
                {
                    TempData["warning"] = "Lob already exists on that account";
                }
                #endregion
            }
            else
            {
                TempData["error"] = "Something went wrong.Please, try again later :/.";
            }
            return RedirectToAction("Create");
        }


        //GET: createLob
        [HttpGet]
        public ActionResult CreateLob()
        {
            ViewBag.AccountID = new SelectList(personal.Accounts, "AccountID", "AccountName");
            ViewBag.DepID = new SelectList(personal.Departments , "DepID", "Department");
            return View();
        }


        //POST: createLob
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateLob(LOBex oBex)
        {
            #region insert Lob in LOB table in HRPersonnal db
            if (ModelState.IsValid)
            {
                var chk_Lob = personal.LOB.Where(x => x.DEPID == oBex.DEPID).Where(x => x.AccountID == oBex.Account_ID).Any(x=>x.LOB1 == oBex.Name);
                if (!chk_Lob)
                {
                    LOB lOB = new LOB();
                    lOB.LOB1 = oBex.Name;
                    lOB.LOBValue = oBex.Name;
                    lOB.DEPID = oBex.DEPID;
                    lOB.AccountID = oBex.Account_ID;
                    lOB.IsActive = true;
                    personal.LOB.Add(lOB);
                    personal.SaveChanges();
                    TempData["success"] = "Lob has been saved successfully :) ! ";
                }
                else
                {
                    TempData["warning"] = "Lob already exists !";
                }

            }
            #endregion
            else
            {
                TempData["error"] = "Something went wrong.Please, try again later :/ !";
            }
            return RedirectToAction("CreateLob");
        }


        //GET: createuser
        [HttpGet]
        public ActionResult CreateUser()
        {
            ViewBag.RoleID = new SelectList(personal.Roles , "RoleID", "Role");
            ViewBag.DepID = new SelectList(personal.Departments, "DepID", "Department");
            return View();
        }


        //POST: createuser
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateUser(PersonnalUser user)
        {
            if (ModelState.IsValid)
            {
                var chk_user = personal.Users.Any(x => x.UserID == user.usrID);
                if (!chk_user)
                {
                    Users usr = new Users();
                    usr.UserID = user.usrID;
                    usr.UserName = user.Name;
                    usr.RoleID = user.Roleid;
                    usr.IsActive = true;
                    usr.GradeID = user.Gradeid;
                    usr.InsertedBy = EmployeeLogin;
                    usr.InsertedOn = DateTime.Now;
                    usr.Email = user.Email;
                    usr.PositionName = user.PositionName;
                    usr.DepartmentName = user.DepartmentName;
                    personal.Users.Add(usr);
                    personal.SaveChanges();
                    TempData["success"] = "User has been saved successfully :) !";
                }
                else
                {
                    TempData["warning"] = "User already exists !";
                }
            }

            return RedirectToAction("CreateUser");
        }


        //GET: create boss-department
        [HttpGet]
        public ActionResult CreateBoss_Dep()
        {
            var get_this_Admin = personal.Users.Where(x => x.RoleID == 1).Where(x => x.IsActive == true).ToList();
            ViewBag.UserID = new SelectList(get_this_Admin.OrderBy(x => x.UserName), "UserID", "UserName");
            ViewBag.Indexs = new SelectList(personal.LOB, "Indexs", "LOB1");
            ViewBag.AccountID = new SelectList(personal.Accounts, "AccountID", "AccountName");
            return View();
        }


        #region populate user's ID with their specified names 

        //populate user's names
        public JsonResult GetUserName_toUserLogin(string usr)
        {
            List<Users> getUser = new List<Users>();
            getUser = (from r in personal.Users where (r.UserID == usr) select r).ToList();
            List<SelectListItem> User_ID = new List<SelectListItem>();

            foreach (Users name in getUser)
            {
                User_ID.Add(new SelectListItem { Text = name.UserID, Value = name.UserName.ToString() });
            }
            return Json(new SelectList(User_ID, "Value", "Text"));

        }
        #endregion

        #region Populates Lobs according to the selected account in the Create boss-department view 
        //populate Lobs
        public JsonResult GetLOB_toAccount(int acc)
        {
            List<LOB> getLob = new List<LOB>();
            getLob = (from r in personal.LOB where (r.AccountID == acc) select r).ToList();
            List<SelectListItem> Lobs = new List<SelectListItem>();

            foreach (LOB lob in getLob)
            {
                Lobs.Add(new SelectListItem { Text = lob.LOB1, Value = lob.Indexs.ToString() });
            }
            return Json(new SelectList(Lobs, "Value", "Text"));
        }
        #endregion


        //POST: create boss-department
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateBoss_Dep(Boss_Dep boss_Dep)
        {
            #region Insert new record for admins only in Boss_Deapartment table in HRLoan database 

            if (ModelState.IsValid)
            {
                var Chk_UsrAccess = personal.Boss_Department.Where(x => x.BossLogin == boss_Dep.BossLogin).Any(x => x.LOBIndexs == boss_Dep.LOBIndexs);
                if (!Chk_UsrAccess)
                {
                    Boss_Department boss_Department = new Boss_Department();
                    boss_Department.BossLogin = boss_Dep.BossLogin;
                    boss_Department.LOBIndexs = boss_Dep.LOBIndexs;
                    boss_Department.IsActive = true;
                    boss_Department.ToMail = boss_Dep.To_mail;
                    boss_Department.InsertedOn = DateTime.Now;
                    boss_Department.UpdatedBy = EmployeeLogin;
                    personal.Boss_Department.Add(boss_Department);
                    personal.SaveChanges();
                    TempData["success"] = "Data saved successfully !";
                }
                else
                {
                    TempData["warning"] = "Data already exists in Boss_Department table !";
                }

            }
            else
            {
                TempData["error"] = "something went wrong :( !";
            }

            return RedirectToAction("CreateBoss_Dep");

            #endregion

        }

    }
}

【问题讨论】:

  • 如果您展示示例代码来展示相似之处和不同之处,将会有所帮助。一般来说,您可以尝试将具有差异的代码移动到每个数据库的业务层,这样可以使控制器变得简单和统一。
  • 取决于相似之处,但将通用代码移动到许多控制器派生的基类中是一种选择。

标签: c# asp.net-mvc entity-framework design-patterns


【解决方案1】:

恭喜您发现代码的重复性。这是一个好的开始。

另一方面,你还有很长的路要走,在这方面,你需要学习很多东西。

在研究您的代码结构后,它看起来像这样:

(1) Controller Class
-- (2) HTTP GET METHOD / ACTION 
-- (3) HTTP POST METHOD / ACTION
-- -- (4) If the model state is valid
-- -- -- (5) If the object does not already exist in the database
-- -- -- -- (6) Do the thing. In your case, create a record in the database and save it.
-- -- -- -- (7) While doing it, if there's an error, write it to TempData.
-- -- -- (8) Else if the object already exists in the database
-- -- -- -- (9) Write an error to the temp data
-- -- -- (10) End of check if the object exists in the database
-- -- (11) Else if the model state is not valid
-- -- -- (12) Write an error to TempData
-- -- (13) End of check if model state is valid or not
-- -- (14) If while doing the whole method thing, there's an error, write it to TempData
-- (15) End of method.

幸运的是,这根本不是一个新问题,甚至不是一个难以破解的问题。它基本上是所有简单的 CRUD 应用程序的主要内容。

问题在于大声而清晰地大喊大叫,而您却预感到出了点问题。这就是问题所在。

一切都搞混了。在复杂的语言中,您是在混合关注点

所以,你需要把你的顾虑分开

这是基本的设计原则,而不是特定的设计模式。

关注点分离

您的代码靠近 UI,即您的控制器操作、您的业务或模型对象,即用户、帐户等类。您的实用程序类(例如将内容转换为 JSON 并返回的方法),所有这些都在一处。

此外,您甚至还创建了执行 JSON 并将业务对象反向转换为公共方法的实用方法,使它们可以作为控制器上的操作调用。

所有这些错误都违反了良好的设计原则。

您需要将这些分开,以便您的代码看起来更像是两三行,如下所示:

public void PostAction(ModelObject model)
{
  if (!ModelState.IsValid)
  {
    // Some error handling strategy common to the whole
    // application that sits well with the kind of interface
    // this application has. Are you making a website or is this
    // a web API?
  }

  // You're here because the model state is valid

  // Get the repository object somehow:
  // (a) Either through dependency injection in the controller's constructor, and
  //     when you get the dependency, get it in the lowest / basest possible interface
  //     so that it is polymorphic.
  // (b) Or as a service location strategy, which means new it up here

  repositoryObject.doTheThing();
}

public class MyCentralErrorHandler : HandleErrorAttribute
{
  ...
}

在分离它们时,我注意到我应用了一些模式:

  1. 依赖注入
  2. 服务地点
  3. 存储库

我也应用了接口隔离的SOLID原则。也就是说,我使用多态编译时类型获得了我的依赖,如下所示:

public class MyController : Controller
{
  public MyController(IRepository repositoryObject) : base()
  {
  }
}

所以,为了回答您关于应用哪种设计模式的问题的另一方面,我想说您仍然落入所有新手都会落入的同一个陷阱。它没有应用您在此阶段需要学习的设计模式。但是您需要编写更多代码。

代码大量练习,直到你自己的直觉发展到这样一个阶段,就像你发现你的代码有些混乱一样,你自己的直觉清楚而明确地告诉你需要什么的界限去哪里,你开始根据你的直觉工作,在按照它的指示结束时,你意识到,“嘿,我刚才所做的,它被称为某某设计模式。维奥拉!我从来没有有意识地这样做过。 "

所以,简而言之,研究它们。现在学习所有的设计模式。彻底学习它们,并给它几年的时间在你的脑海中滚动。然后在编写代码时将它们全部抛诸脑后。你不应该在你的代码上超级强加设计模式。它们应该像便便一样从你身上出来。相信我,它会发生的。你所需要的只是更多年的练习。

同时,编写大量代码。大量代码。

正如我上面已经说过的,对您的问题的另一个实事求是的答案是,您需要应用这些东西:

  1. 关注点分离的设计原则;
  2. 存储库模式,它本身就是关注点分离原则的体现;
  3. 服务地点
  4. 依赖注入
  5. 针对接口而非具体实现进行编程的 SOLID 原则
  6. 正确的错误/异常处理策略。这里有很多想法。你需要问自己很多问题,比如你的应用程序有什么样的界面,以及你打算在每个阶段做什么。这不是我可以在这里写并完成的事情。您需要一位导师或多年的实践经验。

我必须提请您注意的另一件事是设计模式重叠。因此,还有一些更明显的设计模式实际上也有不止一个名称,它们已经应用在我上面强调的解决方案中。它们基本上是同一事物的不同名称。因此,这些都是根据其功能甚至上下文划分的模糊概念。

例如,接口编程原理也可以称为接口隔离,尽管术语接口隔离在系统上下文中具有另一个更广泛的含义设计。 多态性也在起作用。而且我确信还有另一个模式名称可以归因于相同的常识、明显的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2021-04-28
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多