2010-10-15 87 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; 
    } 
} 

很可能有其他的方法来解决这个问题,但是这个固定为我:)