2013-10-03 77 views
3

我正在開發一個新的MVC 5項目。這是一個單一的多租戶站點,允許許多組織和分支機構維護一個頁面。所有頁面先從以下URL格式:你如何重載MVC控制器以避免重複共同代碼?

http://mysite.com/{organisation}/{branch}/... 

例如:

http://mysite.com/contours/albany/... 
http://mysite.com/contours/birkenhead/... 
http://mysite.com/lifestyle/auckland/... 

我宣佈我RouteConfig與{organisation}{branch}{controller}{action}前:

routes.MapRoute(
    name: "Default", 
    url: "{organisation}/{branch}/{controller}/{action}/{id}", 
    defaults: new { controller = "TimeTable", 
        action = "Index", 
        id = UrlParameter.Optional }); 

這工作得很好。然而,每個單一控制器現在在其頂部都有相同的代碼,用於檢查organisationbranch

public ActionResult Index(string organisation, string branch, string name, int id) 
{ 
    // ensure the organisation and branch are valid 
    var branchInst = _branchRepository.GetBranchByUrlPath(organisation, branch); 
    if (branchInst == null) 
    { 
     return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
    } 
    // start the real code here... 
} 

我熱衷於DRY原則(不要重複自己),我想知道是否有可能以某種方式隔離通用代碼,改變我的控制器簽名是這樣的:

public ActionResult Index(Branch branch, string name, int id) 
{ 
    // start the real code here... 
} 

回答

3

您可以創建一個通用控制器並讓其他控制器繼承它。例如:

public class YourCommonController : Controller 
    { 
     protected override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      var organisation = filterContext.RouteData.Values["organisation"]; 
      var branch = filterContext.RouteData.Values["branch"]; 

      // Your validation code here 

      base.OnActionExecuting(filterContext); 
     } 
    } 

現在,只要從YourCommonController繼承,當你想擁有這個共享代碼。

+0

好吧,我已經嘗試過這樣的事情,但即使在驗證後,我的'branchInst'在從此繼承的控制器中不可用。 –

+0

謝謝,這讓我想起了爲什麼這會起作用,並且我終於意識到Controller對象實際上是真正的短命對象,我不必擔心會在上下文之外使用成員級別的變量。這使Controller更清晰地使用了我! –

0

另一種選擇是使用自定義的ActionFilters,這樣你就不必記得繼承你的基礎控制器。 AuthorizeAttribute是一個很好的重載,因爲這是你想要做的。

http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

public class ValidationActionFilter : AuthorizeAttribute 

{ 
     public override void OnAuthorization(AuthorizationContext filterContext) 
     { 
      var routeData = filterContext.RouteData; 
      var branchInst = _branchRepository.GetBranchByUrlPath(routeData.Values["organisation"], routeData.Values["branch"]); 
      if (branchInst == null) 
      { 
       filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
      } 
     } 
} 

在你的Global.asax或一個FilterConfig類,你可以然後只需註冊它

GlobalFilters.Filters.Add(new ValidationActionFilter()); 

沒有測試代碼,但你的想法..

1

我不得不在用戶標識和標記通過POST傳遞給每個控制器操作的應用程序中執行類似的操作(由於一些非常舊的傳統身份驗證,我們是doi NG)。

我聲明瞭一個BaseController,並讓每個控制器繼承該基本控制器。因此,每個繼承基礎的控制器都可以訪問標準的uid和標記屬性(如果他們需要它們的話),並且這些屬性在每個操作開始時已經從HTTP上下文中檢索到。

public abstract class BaseController : Controller 
    { 
     #region Properties 

     protected string uid; 
     protected string token; 

     #endregion 

     #region Event overloads 

     protected override void Initialize(System.Web.Routing.RequestContext requestContext) 
     {  
      try 
      { 
       uid = requestContext.HttpContext.Request["uid"]; 
       token = requestContext.HttpContext.Request["token"]; 

       if (uid != null && token != null) 
       { 
        ViewBag.uid = uid; 

        if (!token.Contains("%")) 
         ViewBag.token = requestContext.HttpContext.Server.UrlEncode(token); 
        else 
         ViewBag.token = token; 

        base.Initialize(requestContext); 
       } 
       else 
       { 
        requestContext.HttpContext.Response.Redirect(ConfigurationManager.AppSettings.GetValues("rsLocation")[0]); 
       } 
      } 
      // User ID is not in the query string 
      catch (Exception ex) 
      { 
       requestContext.HttpContext.Response.Redirect(ConfigurationManager.AppSettings.GetValues("redirectLocation")[0]); 
      } 
     } 

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

     #endregion 
    } 

現在,您可以繼承您的「真實」控制器中的基礎控制器。

public class TestController : BaseController 
    { 
     #region Controller actions 

     // 
     // GET: /Index/  

     [Authorize] 
     public ViewResult Index() 
     { 
      //blah blah blah 
     } 
    } 

在你的情況,你會尋找組織和分支,而不是uid和令牌,但它是相同的想法。