C# MVC5控制器含return的重复代码复用问题(DRY原则)
解决带return语句的重复Controller代码优化问题
这问题我之前做ASP.NET MVC项目时也碰到过!带return的重复代码确实没法直接抽成普通方法(因为return会直接终止原方法),不过有几种实用的办法能搞定,既符合DRY原则又不破坏原有逻辑:
方法一:封装成返回ActionResult的私有方法
把重复的逻辑和return分支封装成一个私有方法,让它返回ActionResult或者null——授权通过时返回null,需要终止原方法时返回对应的结果(比如跳转、视图等)。原方法调用这个私有方法后,判断结果是否为null,非null就直接return,否则继续执行自己的逻辑。
示例代码:
public class ExampleController : Controller { private Authorizer _authorizer = new Authorizer(); // 抽取的重复授权检查逻辑 private ActionResult CheckEditAuthorization(int id) { var result = _authorizer.EditThing(id); if (!result.CanEditPartA) { // 记录非法访问日志 // 其他重复操作 return RedirectToAction("AccessDenied", "Home"); // 替换成你原来的return内容 } return null; // 授权通过,返回null让原方法继续执行 } public ActionResult Edit(int id) { var authResponse = CheckEditAuthorization(id); if (authResponse != null) { return authResponse; } // 原方法的核心逻辑,不用再写重复代码了 var model = FetchThingById(id); return View(model); } // 另一个需要相同检查的Action public ActionResult Delete(int id) { var authResponse = CheckEditAuthorization(id); if (authResponse != null) { return authResponse; } // Delete的核心逻辑 RemoveThingById(id); return RedirectToAction("Index"); } }
方法二:使用ActionFilterAttribute(更优雅的复用方式)
如果多个Action都需要这套重复的前置检查,用ASP.NET MVC的过滤器会更合适。把重复逻辑放到自定义的ActionFilter里,然后在需要的Action上标记属性即可,完全解耦授权逻辑和业务逻辑。
示例代码:
// 自定义授权过滤器 public class EditAuthorizationFilter : ActionFilterAttribute { private Authorizer _authorizer = new Authorizer(); public override void OnActionExecuting(ActionExecutingContext filterContext) { // 从Action参数中获取id if (filterContext.ActionParameters.TryGetValue("id", out var idObj) && idObj is int id) { var result = _authorizer.EditThing(id); if (!result.CanEditPartA) { // 记录非法访问日志 // 其他重复操作 // 设置返回结果,终止原Action执行 filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Home" }, { "action", "AccessDenied" } }); } } base.OnActionExecuting(filterContext); } } // 在Controller中使用过滤器 public class ExampleController : Controller { [EditAuthorizationFilter] public ActionResult Edit(int id) { // 原方法核心逻辑 var model = FetchThingById(id); return View(model); } [EditAuthorizationFilter] public ActionResult Delete(int id) { // Delete核心逻辑 RemoveThingById(id); return RedirectToAction("Index"); } }
选择建议
- 如果只是2-3个Action有重复逻辑,方法一简单直接,不用额外定义过滤器;
- 如果有大量Action需要相同的前置检查,方法二更优雅,扩展性更强,后续修改授权逻辑只需要改过滤器就行。
内容的提问来源于stack exchange,提问作者Luke Hammer
相关产品推荐
相关产品推荐

