2010-10-15 88 views
0

我有點問題。我有一個叫做框架的區域。這個區域有一個家庭控制器。該網站的默認設置也有一個家庭控制器。MVC 2.0,結構圖,區域和重複的控制器名稱

我想要做的是有適用於IFrame的每個控制器/操作的版本,以及是正常站點的版本。我通過母版頁執行此操作,並且網站母版頁擁有許多與框架版本不同的內容佔位符。出於這個原因,我不能只交換母版頁。例如,http://example.com/Framed/Account/Index將顯示一個非常基本的版本,只有您的帳戶信息用於外部網站。 http://example.com/Account/Index將顯示相同的數據,但在默認站點內。

我的IoC容器是結構圖。所以我找到了http://odetocode.com/Blogs/scott/archive/2009/10/19/mvc-2-areas-and-containers.aspxhttp://odetocode.com/Blogs/scott/archive/2009/10/13/asp-net-mvc2-preview-2-areas-and-routes.aspx。這是我目前的設置。

Structuremap初始化

ObjectFactory.Initialize(x => 
      { 
       x.AddRegistry(new ApplicationRegistry()); 
       x.Scan(s => 
       { 
        s.AssembliesFromPath(HttpRuntime.BinDirectory); 
        s.AddAllTypesOf<IController>() 
         .NameBy(type => type.Namespace + "." + type.Name.Replace("Controller", "")); 
       }); 
      }); 

在這裏,我通過調試中發現的問題是,由於該控制器具有相同的名稱(HomeController中),它只註冊了第一個,這是默認的主控制器。我有創意並附加了命名空間,以便它能夠註冊我的所有控制器。

默認路由

routes.MapRoute(
       "Default", // Route name 
       "{controller}/{action}/{id}", // URL with parameters 
       new { area = "", controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults 
       new[] { "MySite.Controllers" } 
       ); 

地區航線

context.MapRoute(
       "Framed_default", 
       "Framed/{controller}/{action}/{id}", 
       new { area = "Framed", controller = "Home", action = "Index", id = UrlParameter.Optional }, 
       new string[] { "MySite.Areas.Framed.Controllers" } 
      ); 

所推薦的Phil Haack,我使用的命名空間作爲第四個參數

應用開始,只是爲了證明初始化順序

protected void Application_Start() 
     { 
      InitializeControllerFactory(); 

      AreaRegistration.RegisterAllAreas(); 

      RouteConfiguration.RegisterRoutes(); 
     } 

器廠

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
     { 
      IController result = null; 
      if (controllerType != null) 
      { 
       result = ObjectFactory.GetInstance(controllerType) 
        as IController; 
      } 
      return result; 
     } 

所以,當我打/首頁/指數,它通過在正確的控制器類型。當我點擊/ Framed/Home/Index時,controllerType爲空,因爲沒有控制器被返回而出現錯誤。

就好像MVC完全忽略了我的區域一樣。這裏發生了什麼?我究竟做錯了什麼?

回答

0

如果有人試圖做類似的事情,我用這個帖子的想法:Categories of controllers in MVC Routing? (Duplicate Controller names in separate Namespaces)我不得不使用區域完全轉儲並自己實現一些東西。

我有控制器/ HomeController.cs和控制器/幀/ HomeController.cs

我有一個類ControllerBase這在所有的控制器/控制器從繼承。我有從ControllerBase繼承的AreaController,其中/ Controllers/Framed中的所有控制器都從其中繼承。

這是我區Controller類

public class AreaController : ControllerBase 
    { 
     private string Area 
     { 
      get 
      { 
       return this.GetType().Namespace.Replace("MySite.Controllers.", ""); 
      } 
     } 
     protected override ViewResult View(string viewName, string masterName, object model) 
     { 
      string controller = this.ControllerContext.RequestContext.RouteData.Values["controller"].ToString(); 

      if (String.IsNullOrEmpty(viewName)) 
       viewName = this.ControllerContext.RequestContext.RouteData.Values["action"].ToString(); 

      return base.View(String.Format("~/Views/{0}/{1}/{2}.aspx", Area, controller, viewName), masterName, model); 
     } 

     protected override PartialViewResult PartialView(string viewName, object model) 
     { 
      string controller = this.ControllerContext.RequestContext.RouteData.Values["controller"].ToString(); 

      if (String.IsNullOrEmpty(viewName)) 
       viewName = this.ControllerContext.RequestContext.RouteData.Values["action"].ToString(); 

      PartialViewResult result = null; 

      result = base.PartialView(String.Format("~/Views/{0}/{1}/{2}.aspx", Area, controller, viewName), model); 

      if (result != null) 
       return result; 

      result = base.PartialView(String.Format("~/Views/{0}/{1}/{2}.ascx", Area, controller, viewName), model); 

      if (result != null) 
       return result; 

      result = base.PartialView(viewName, model); 

      return result; 
     } 
    } 

我不得不重寫視圖和partialview方法。這樣,我的「區域」中的控制器就可以使用視圖和分支的默認方法,並支持添加的文件夾結構。

至於視圖,我有Views/Home/Index.aspx和Views/Framed/Home/Index.aspx。我用的路由如圖所示的職位,但這裏是我的樣子供參考:

var testNamespace = new RouteValueDictionary(); 
      testNamespace.Add("namespaces", new HashSet<string>(new string[] 
      { 
       "MySite.Controllers.Framed" 
      })); 

      //for some reason we need to delare the empty version to support /framed when it does not have a controller or action 
      routes.Add("FramedEmpty", new Route("Framed", new MvcRouteHandler()) 
      { 
       Defaults = new RouteValueDictionary(new 
       { 
        controller = "Home", 
        action = "Index", 
        id = UrlParameter.Optional 
       }), 
       DataTokens = testNamespace 
      }); 

      routes.Add("FramedDefault", new Route("Framed/{controller}/{action}/{id}", new MvcRouteHandler()) 
      { 
       Defaults = new RouteValueDictionary(new 
       { 
        //controller = "Home", 
        action = "Index", 
        id = UrlParameter.Optional 
       }), 
       DataTokens = testNamespace 
      }); 

var defaultNamespace = new RouteValueDictionary(); 
      defaultNamespace.Add("namespaces", new HashSet<string>(new string[] 
      { 
       "MySite.Controllers" 
      })); 

routes.Add("Default", new Route("{controller}/{action}/{id}", new MvcRouteHandler()) 
       { 
        Defaults = new RouteValueDictionary(new 
        { 
         controller = "Home", 
         action = "Index", 
         id = UrlParameter.Optional 
        }), 
        DataTokens = defaultNamespace 
       }); 

現在我可以去同一個站點/主頁/索引或/幀/首頁/指數,並得到兩種不同的看法共享控制。理想情況下,我希望一個控制器返回2個視圖中的一個,但我不知道如何在沒有2個控制器的情況下完成這項工作。

0

我有一個類似的問題使用Structuremap與區域。我有一個名爲Admin的區域,無論何時您嘗試去/ admin,它都會使用null控制器類型到達StructureMap控制器工廠。

我固定它通過下面這篇博客文章: http://stephenwalther.com/blog/archive/2008/08/07/asp-net-mvc-tip-30-create-custom-route-constraints.aspx

必須添加上的缺省路由的約束,如果控制器是管理員無法比擬的。

這裏是我的默認路由定義:

routes.MapRoute(
    "Default", 
    "{controller}/{action}/{id}", 
    new { controller = "MyController", action = "AnAction", id = UrlParameter.Optional }, 
    new { controller = new NotEqualConstraint("Admin")}, 
    new string[] {"DailyDealsHQ.WebUI.Controllers"} 
); 

和這裏的NotEqualConstraint執行:

public class NotEqualConstraint : IRouteConstraint 
{ 
    private string match = String.Empty; 

    public NotEqualConstraint(string match) 
    { 
     this.match = match; 
    } 

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     return String.Compare(values[parameterName].ToString(), match, true) != 0; 
    } 
} 

很可能有其他的方法來解決這個問題,但是這個固定爲我:)