2012-06-19 20 views
0

我试图从我的管理区域内执行错误重定向到我的错误视图,该视图在所有区域之外共享。从一个区域重定向到一个控制器/视图不在一个区域

我在我的大厅控制器称为错误创建的方法,包括:

public ViewResult Error() 
    { 
     return View("Views/Shared/Error"); 
    } 

视图中查看/共享目录存在,被称为错误。

从在管理方面我的用户控制,我试图做的事:

return RedirectToAction("Error", "Lobby", new {area = ""}); 

然而,应用程序试图以“/管理/大堂/错误”重定向尽管有面积=我的“”在路径值中。当我尝试遍历代码时,在上一行和浏览器中的404错误之间没有执行任何行。

缺少什么我在这里?

编辑添加:实际上我的路线可能有问题。我尝试更改登录后的默认行为以指向不在某个区域的控制器,并且它自动尝试将我发送到我的管理员区域。

我想要实现的是:我想要有一个区域的路由被解释为需要去那个区域,并且没有区域的路由使用默认。目前我只有一个区域(管理员),虽然会有更多。

这里是我的路线:

routes.MapRoute("ErrorPage", "Error", new { controller="Error", action="Error" }, new[] { "WebUI.Controllers" }); //Error Route 

     routes.MapRoute(
      "", // Route name 
      "Admin/{controller}/{action}/{id}", // URL with parameters 
      new { area ="Admin", controller = "Client", action = "ManageClients", id = UrlParameter.Optional } // Parameter defaults 
      , new[] { "WebUI.Areas.Admin.Controllers" } //prioritize admin 
     ); 

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

IIRC当我试图具有没有“硬编码”“admin”作为区域名称的路由,路由引擎试图东西航线W/O区域进入区域路线,导致控制器被误认为控制器的区域和动作。

但是我怀疑它现在在做什么是以某种方式将“/ Admin”附加到我的所有路线! 例如,应用程序在启动时首先进入帐户/登录(不在区域中)。当我将登录行为更改为:

 return RedirectToAction("Summary", "Logging"); 

它正在形成url/Admin/Logging/Summary而不是/ Logging/Summary。 即使我手动将其更改为

return RedirectToAction("Summary", "Logging", new {area=""}); 

它必须从路线走的是“默认”管理区域。但是,如果我从路线中删除默认区域,则我的管理链接全部中断。

这是我区登记的样子:

public override void RegisterArea(AreaRegistrationContext context) 
    { 
     context.MapRoute(
      "Admin_default", 
      "Admin/{controller}/{action}/{id}", 
      new { action = "Index", id = UrlParameter.Optional }, 
     new [] { "WebUI.Areas.Admin.Controllers" } 
     ); 
    } 

所以我想我需要我的问题改写到:我怎么配置的领域和途径,使路线&联系内外的区域功能正常吗?

+1

您是否以可能解释此方式的方式更改默认路由表? –

+0

实际上它确实看起来像路线是什么搞乱了这一点,但我不知道如何解决。我已经为原始问题添加了额外的信息,也许这将揭示我做错了什么。谢谢! – anyeone

+0

您的区域注册应该照顾您需要的所有与管理区域。我不知道你所有路线的第一部分是你手动整理所有路线,还是你在RegisterRoutes全局方法中实际上有第二条路线声明。如果你确实在地区注册之外还有那个,我建议把它从全球范围内拿出来。除此之外,你应该考虑安装Glimpse或类似的东西,看看在MVC中匹配的路由究竟发生了什么。 –

回答

0

我最终通过修改菲尔哈克的AreaRouteHelper扩展有所解决问题:

public static class AreaRouteHelper 
{ 
    public static void MapAreas(this RouteCollection routes, string url, string rootNamespace, string[] areas) 
    { 
     Array.ForEach(areas, area => 
     { 
      Route route = new Route("{area}/" + url, new MvcRouteHandler()); 
      route.Constraints = new RouteValueDictionary(new { area }); 
      string areaNamespace = rootNamespace + ".Areas." + area + ".Controllers"; 
      route.DataTokens = new RouteValueDictionary(new { namespaces = new string[] { areaNamespace } }); 
      route.Defaults = new RouteValueDictionary(new { action = "Index", controller = "Landing", id = "" }); 
      routes.Add(route); 
     }); 
    } 

    public static void MapRootArea(this RouteCollection routes, string url, string rootNamespace, object defaults) 
    { 
     Route route = new Route(url, new MvcRouteHandler()); 
     route.DataTokens = new RouteValueDictionary(new { namespaces = new string[] { rootNamespace + ".Controllers" } }); 
     route.Defaults = new RouteValueDictionary(new { area = "", action = "Index", controller = "Lobby", id = "" }); 
     routes.Add(route); 
    } 
} 

(基本上我只好从默认RootArea默认删除单词“根”并更改默认为“大房间”和“着陆”,这是我们的标准,而不是家庭,当我在那里留下了他默认的“根”,它增加了“根”的文件夹结构,没有工作)

然后我删除了第二分两路从我的RegisterRoutes并换成:

routes.MapAreas("{controller}/{action}/{id}", "WebUI", new[] { "Admin", "Analysis" }); 

     routes.MapRootArea("{controller}/{action}/{id}", 
      "WebUI", 
      new { controller = "Lobby", action = "Index", id = "" }); 

此修复需要区域感知视图引擎。 Haack项目中的一个是一个1.0 webform视图引擎,我已经有一个区域感知剃须刀视图引擎,我从另一个帖子在某个地方刮过,这个工作正常。我真的不记得我发现了什么后,或者我直接链接到它,以信任作者。但这就是它的样子(如果这里有人知道是谁写的,我会很乐意将它归类给那个人)。请注意,这里的映射匹配我的项目,如果不进行某些调整,可能无法与其他任何人匹配!

public class RazorAreaAwareViewEngine :RazorViewEngine 
{ 
    private static readonly string[] EmptyLocations = { }; 

    public RazorAreaAwareViewEngine() 
    { 
     MasterLocationFormats = new string[] 
            { 
             "~/Views/{1}/{0}.master", 
             "~/Views/Shared/{0}.master" 
            }; 
     ViewLocationFormats = new string[] 
            { 
             "~/Areas/{2}/Views/{1}/{0}.cshtml", 
             "~/Areas/{2}/Views/Shared/{0}.cshtml", 
             "~/{2}/{0}.cshtml", 
             "~/Views/{1}/{0}.cshtml", 
             "~/Views/Shared/{0}.cshtml", 
            }; 
     PartialViewLocationFormats = ViewLocationFormats; 
    } 
    public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName,string masterName, bool useCache) 
    { 
     if (controllerContext == null) 
     { 
      throw new ArgumentNullException("controllerContext"); 
     } 
     if (string.IsNullOrEmpty(viewName)) 
     { 
      throw new ArgumentNullException(viewName, 
       "Value cannot be null or empty."); 
     } 
     string area = GetArea(controllerContext); 

     return FindAreaView(controllerContext, area, viewName, 
      masterName, useCache); 
    } 

    public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName,bool useCache) 
    { 
     if (controllerContext == null) 
     { 
      throw new ArgumentNullException("controllerContext"); 
     } 
     if (string.IsNullOrEmpty(partialViewName)) 
     { 
      throw new ArgumentNullException(partialViewName, 
       "Value cannot be null or empty."); 
     } 
     string area = GetArea(controllerContext); 

     return FindAreaPartialView(controllerContext, area, 
      partialViewName, useCache); 
    } 

    protected string GetArea(ControllerContext controllerContext) 
    { 
     object area = null; 
     if (controllerContext.RouteData.DataTokens.ContainsKey("area")) 
     { 
      area = controllerContext.RouteData.DataTokens["area"]; 
     } 
     if (area == null) 
     { 
      controllerContext.RouteData.Values.TryGetValue("area", out area); 
     } 
     if(area !=null) 
     { 
      return area.ToString(); 
     } 
     return null; 
    } 

    protected virtual ViewEngineResult FindAreaView(ControllerContext controllerContext, string areaName, string viewName,string masterName, bool useCache) 
    { 
     string controllerName = 
      controllerContext.RouteData.GetRequiredString("controller"); 
     string[] searchedViewPaths; 
     string viewPath = GetPath(controllerContext, ViewLocationFormats, 
      "ViewLocationFormats", viewName, controllerName, areaName, "View", 
      useCache, out searchedViewPaths); 
     string[] searchedMasterPaths; 
     string masterPath = GetPath(controllerContext, MasterLocationFormats, 
      "MasterLocationFormats", masterName, controllerName, areaName, 
      "Master", useCache, out searchedMasterPaths); 
     if (!string.IsNullOrEmpty(viewPath) && 
      (!string.IsNullOrEmpty(masterPath) || 
       string.IsNullOrEmpty(masterName))) 
     { 
      return new ViewEngineResult(CreateView(controllerContext, viewPath, 
       masterPath), this); 
     } 
     return new ViewEngineResult(
      searchedViewPaths.Union<string>(searchedMasterPaths)); 
    } 

    protected virtual ViewEngineResult FindAreaPartialView(ControllerContext controllerContext, string areaName,string viewName, bool useCache) 
    { 
     string controllerName = 
      controllerContext.RouteData.GetRequiredString("controller"); 
     string[] searchedViewPaths; 
     string partialViewPath = GetPath(controllerContext, 
      ViewLocationFormats, "PartialViewLocationFormats", viewName, 
      controllerName, areaName, "Partial", useCache, 
      out searchedViewPaths); 
     if (!string.IsNullOrEmpty(partialViewPath)) 
     { 
      return new ViewEngineResult(CreatePartialView(controllerContext, 
       partialViewPath), this); 
     } 
     return new ViewEngineResult(searchedViewPaths); 
    } 

    protected string CreateCacheKey(string prefix, string name, 
     string controller, string area) 
    { 
     return string.Format(CultureInfo.InvariantCulture, 
      ":ViewCacheEntry:{0}:{1}:{2}:{3}:{4}:", 
      base.GetType().AssemblyQualifiedName, 
      prefix, name, controller, area); 
    } 

    protected string GetPath(ControllerContext controllerContext,string[] locations, string locationsPropertyName, string name, 
     string controllerName, string areaName, string cacheKeyPrefix,bool useCache, out string[] searchedLocations) 
    { 
     searchedLocations = EmptyLocations; 
     if (string.IsNullOrEmpty(name)) 
     { 
      return string.Empty; 
     } 
     if ((locations == null) || (locations.Length == 0)) 
     { 
      throw new InvalidOperationException(string.Format("The property " + 
       "'{0}' cannot be null or empty.", locationsPropertyName)); 
     } 
     bool isSpecificPath = IsSpecificPath(name); 
     string key = CreateCacheKey(cacheKeyPrefix, name, 
      isSpecificPath ? string.Empty : controllerName, 
      isSpecificPath ? string.Empty : areaName); 
     if (useCache) 
     { 
      string viewLocation = ViewLocationCache.GetViewLocation(
       controllerContext.HttpContext, key); 
      if (viewLocation != null) 
      { 
       return viewLocation; 
      } 
     } 
     if (!isSpecificPath) 
     { 
      return GetPathFromGeneralName(controllerContext, locations, name, 
       controllerName, areaName, key, ref searchedLocations); 
     } 
     return GetPathFromSpecificName(controllerContext, name, key, 
      ref searchedLocations); 
    } 

    protected string GetPathFromGeneralName(ControllerContext controllerContext,string[] locations, string name, string controllerName, 
     string areaName, string cacheKey, ref string[] searchedLocations) 
    { 
     string virtualPath = string.Empty; 
     searchedLocations = new string[locations.Length]; 
     for (int i = 0; i < locations.Length; i++) 
     { 
      if (string.IsNullOrEmpty(areaName) && locations[i].Contains("{2}")) 
      { 
       continue; 
      } 
      string testPath = string.Format(CultureInfo.InvariantCulture, 
       locations[i], name, controllerName, areaName); 
      if (FileExists(controllerContext, testPath)) 
      { 
       searchedLocations = EmptyLocations; 
       virtualPath = testPath; 
       ViewLocationCache.InsertViewLocation(
        controllerContext.HttpContext, cacheKey, virtualPath); 
       return virtualPath; 
      } 
      searchedLocations[i] = testPath; 
     } 
     return virtualPath; 
    } 

    protected string GetPathFromSpecificName(ControllerContext controllerContext, string name, string cacheKey,ref string[] searchedLocations) 
    { 
     string virtualPath = name; 
     if (!FileExists(controllerContext, name)) 
     { 
      virtualPath = string.Empty; 
      searchedLocations = new string[] { name }; 
     } 
     ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, 
      cacheKey, virtualPath); 
     return virtualPath; 
    } 

    protected static bool IsSpecificPath(string name) 
    { 
     char ch = name[0]; 
     if (ch != '~') 
     { 
      return (ch == '/'); 
     } 
     return true; 
    } 


} 

内外地区做了这些改变,操作链接后,正确生成和我可以路线内外&以外的地区。

相关问题