2013-10-03 3 views
3

새로운 MVC 5 프로젝트를 만들고 있습니다. 하나의 멀티 테넌트 사이트로 많은 조직과 지점에서 페이지를 관리 할 수 ​​있습니다. 모든 페이지는 다음과 같은 URL 형식으로 시작 :공통 코드 반복을 피하기 위해 MVC 컨트롤러를 어떻게 오버로드합니까?

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

예를 들어 :

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

:

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

은 내가 {controller}{action} 전에 {organisation}{branch} 내 RouteConfig을 선언했습니다 이것은 잘 작동하고 있습니다. 그러나 모든 단일 컨트롤러는 이제 코드 상단에 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

감사합니다.이게 내가이 일을하는 이유에 대해 열심히 생각하게 만들었고 마침내 컨트롤러 객체가 실제로는 수명이 짧은 객체라는 사실을 깨달았습니다. 멤버 수준 변수가 문맥 밖으로 사용되지 않을까 걱정할 필요가 없었습니다. 이로 인해 컨트롤러 사용이 훨씬 명확 해졌습니다! –

0

또 다른 대안으로 사용자 지정 ActionFilters를 사용하면 기본 컨트롤러를 상속하지 않아도됩니다. AuthorizeAttribute는 원하는대로 오버로드하는 것이 좋습니다.

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

당신의 Global.asax에 또는 FilterConfig 클래스에서
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); 
      } 
     } 
} 

당신은 단순히 .. 그것

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

코드를 테스트하지 않습니다하지만 당신은 아이디어를 얻을 I가 있었다

1

을 등록 할 수 있습니다 사용자 ID와 토큰이 POST를 통해 모든 컨트롤러 작업에 전달되는 응용 프로그램에서 비슷한 작업을 수행하십시오 (우리가 수행 한 아주 오래된 레거시 인증 때문에 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 및 토큰 대신 조직 및 분기를 찾고 싶지만 동일한 생각입니다.

관련 문제