如何在 MVC 中设置默认路由(到某个区域)

Posted

技术标签:

【中文标题】如何在 MVC 中设置默认路由(到某个区域)【英文标题】:How to set a Default Route (To an Area) in MVC 【发布时间】:2011-01-09 13:24:29 【问题描述】:

好的,之前有人问过这个问题,但是没有可靠的解决方案。所以为了我自己和其他可能觉得这很有用的人。

在 MVC2 (ASP.NET) 中,我想要它,因此当有人导航到该网站时,会指定一个默认区域。因此,导航到我的网站应该会将您发送到 AreaZ 中的 ControllerX ActionY。

在 Global.asax 中使用以下路由

routes.MapRoute(
                "Area",
                "",
                new  area = "AreaZ", controller = "ControllerX ", action = "ActionY " 
            );

现在这可以正常工作,因为它会尝试提供正确的页面。但是 MVC 继续在站点的根目录中而不是在区域文件夹中查找视图。

有没有办法解决这个问题?

编辑

有一个“解决方案”,在 ControllerX 中,ActionY 返回视图的完整路径。有点破解,但它确实有效。不过我希望有更好的解决方案。

         public ActionResult ActionY()
        
            return View("~/Areas/AreaZ/views/ActionY.aspx");
        

编辑:

当有页面的 html ActionLink 时,这也会成为一个问题。如果未设置区域,则操作链接输出为空白。

所有这些都是设计的还是缺陷?

【问题讨论】:

【参考方案1】:

这个我很感兴趣,我终于有机会研究它了。其他人显然不明白这是 finding view 的问题,而不是 routing 本身的问题 - 这可能是因为您的问题标题表明它是关于路由。

在任何情况下,由于这是一个与视图相关的问题,因此获得所需内容的唯一方法是覆盖默认视图引擎。通常,当您这样做时,只是为了切换视图引擎(即切换到 Spark、NHaml 等)。在这种情况下,我们需要重写的不是视图创建逻辑,而是VirtualPathProviderViewEngine 类中的FindPartialViewFindView 方法。

感谢你的幸运星,这些方法实际上是虚拟的,因为 VirtualPathProviderViewEngine 中的其他所有内容甚至都可访问 - 它是私有的,这使得它非常 em> 重写查找逻辑很烦人,因为如果您希望它与位置缓存和位置格式很好地配合,您基本上必须重写一半已经编写的代码。在对 Reflector 进行了一些挖掘之后,我终于想出了一个可行的解决方案。

我在这里所做的是首先创建一个抽象的AreaAwareViewEngine,它直接派生自VirtualPathProviderViewEngine,而不是WebFormViewEngine。我这样做是为了如果你想创建 Spark 视图(或其他),你仍然可以使用这个类作为基类型。

下面的代码相当冗长,所以给你一个快速总结它的实际作用:它可以让你将2 放入位置格式,它对应于区域名称,同样的方式@987654329 @ 对应于控制器名称。而已!这就是我们必须编写所有这些代码的目的:

BaseAreaAwareViewEngine.cs

public abstract class BaseAreaAwareViewEngine : VirtualPathProviderViewEngine

    private static readonly string[] EmptyLocations =  ;

    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 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 string getArea(ControllerContext controllerContext)
    
        // First try to get area from a RouteValue override, like one specified in the Defaults arg to a Route.
        object areaO;
        controllerContext.RouteData.Values.TryGetValue("area", out areaO);

        // If not specified, try to get it from the Controller's namespace
        if (areaO != null)
            return (string)areaO;

        string namespa = controllerContext.Controller.GetType().Namespace;
        int areaStart = namespa.IndexOf("Areas.");
        if (areaStart == -1)
            return null;

        areaStart += 6;
        int areaEnd = namespa.IndexOf('.', areaStart + 1);
        string area = namespa.Substring(areaStart, areaEnd - areaStart);
        return area;
    

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

现在如上所述,这不是一个具体的引擎,因此您也必须创建它。幸运的是,这部分要容易得多,我们需要做的就是设置默认格式并实际创建视图:

AreaAwareViewEngine.cs

public class AreaAwareViewEngine : BaseAreaAwareViewEngine

    public AreaAwareViewEngine()
    
        MasterLocationFormats = new string[]
        
            "~/Areas/2/Views/1/0.master",
            "~/Areas/2/Views/1/0.cshtml",
            "~/Areas/2/Views/Shared/0.master",
            "~/Areas/2/Views/Shared/0.cshtml",
            "~/Views/1/0.master",
            "~/Views/1/0.cshtml",
            "~/Views/Shared/0.master"
            "~/Views/Shared/0.cshtml"
        ;
        ViewLocationFormats = new string[]
        
            "~/Areas/2/Views/1/0.aspx",
            "~/Areas/2/Views/1/0.ascx",
            "~/Areas/2/Views/1/0.cshtml",
            "~/Areas/2/Views/Shared/0.aspx",
            "~/Areas/2/Views/Shared/0.ascx",
            "~/Areas/2/Views/Shared/0.cshtml",
            "~/Views/1/0.aspx",
            "~/Views/1/0.ascx",
            "~/Views/1/0.cshtml",
            "~/Views/Shared/0.aspx"
            "~/Views/Shared/0.ascx"
            "~/Views/Shared/0.cshtml"
        ;
        PartialViewLocationFormats = ViewLocationFormats;
    

    protected override IView CreatePartialView(
        ControllerContext controllerContext, string partialPath)
    
        if (partialPath.EndsWith(".cshtml"))
            return new System.Web.Mvc.RazorView(controllerContext, partialPath, null, false, null);
        else
            return new WebFormView(controllerContext, partialPath);
    

    protected override IView CreateView(ControllerContext controllerContext,
        string viewPath, string masterPath)
    
        if (viewPath.EndsWith(".cshtml"))
            return new RazorView(controllerContext, viewPath, masterPath, false, null);
        else
            return new WebFormView(controllerContext, viewPath, masterPath);
    

请注意,我们在标准 ViewLocationFormats 中添加了一些条目。这些是新的2 条目,其中2 将映射到我们放入RouteDataarea。我已经单独留下了MasterLocationFormats,但显然你可以根据需要更改它。

现在修改您的global.asax 以注册此视图引擎:

Global.asax.cs

protected void Application_Start()

    RegisterRoutes(RouteTable.Routes);
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new AreaAwareViewEngine());

...并注册默认路由:

public static void RegisterRoutes(RouteCollection routes)

    routes.IgnoreRoute("resource.axd/*pathInfo");
    routes.MapRoute(
        "Area",
        "",
        new  area = "AreaZ", controller = "Default", action = "ActionY" 
    );
    routes.MapRoute(
        "Default",
        "controller/action/id",
        new  controller = "Home", action = "Index", id = "" 
    );

现在创建我们刚刚引用的AreaController

DefaultController.cs(在 ~/Controllers/ 中)

public class DefaultController : Controller

    public ActionResult ActionY()
    
        return View("TestView");
    

显然我们需要目录结构和视图来配合它——我们将保持这个超级简单:

TestView.aspx(在 ~/Areas/AreaZ/Views/Default/ 或 ~/Areas/AreaZ/Views/Shared/ 中)

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<h2>TestView</h2>
This is a test view in AreaZ.

就是这样。 终于,我们完成了

在大多数情况下,您应该能够将 BaseAreaAwareViewEngineAreaAwareViewEngine 放入任何 MVC 项目中,因此即使完成此操作需要大量代码,您只需编写一次。之后,只需在global.asax.cs 中编辑几行并创建您的站点结构即可。

【讨论】:

这很可能是当前最好的解决方案,但远非理想。如上所述,一旦添加 Actionlink 或存在相同的问题。 @Pino:我认为您应该能够通过将相同的area = "AreaZ" 添加到global.asax.cs 中的“默认”路由映射来解决ActionLink 问题。不过我并不积极;试试看。 在 MVC4 中“默认”路由声明从 Global.asax 移动到 ~/App_Start/RouteConfig.cs/RegisterRoutes() 我讨厌投反对票,但我真的不敢相信@Chris Alderson 的以下回答没有获得更多选票。这是一个比这个更简单的解决方案,并且似乎解决了边缘情况(ActionLinks 等)。 这里似乎有一个错误。例如,名为“Re”的区域的视图将位于 ~/Areas/Re/Views/Ctrlr/blah.aspx,但此处的代码使用 ~/2/1/0,即 ~ /Re/Ctrl/blah.aspx,路径中缺少关键区域目录。它应该是“~/Areas/2/Views/1/0.aspx”【参考方案2】:

我就是这样做的。我不知道为什么 MapRoute() 不允许您设置区域,但它确实返回了路线对象,因此您可以继续进行任何您想要的其他更改。我使用它是因为我有一个模块化 MVC 站点,该站点出售给企业客户,他们需要能够将 dll 放入 bin 文件夹以添加新模块。我允许他们在 AppSettings 配置中更改“HomeArea”。

var route = routes.MapRoute(
                "Home_Default", 
                "", 
                new controller = "Home", action = "index" ,
                new[]  "IPC.Web.Core.Controllers" 
               );
route.DataTokens["area"] = area;

编辑:您也可以在 AreaRegistration.RegisterArea 中尝试让用户默认进入的区域。我还没有测试过,但是 AreaRegistrationContext.MapRoute 确实为你设置了route.DataTokens["area"] = this.AreaName;

context.MapRoute(
                    "Home_Default", 
                    "", 
                    new controller = "Home", action = "index" ,
                    new[]  "IPC.Web.Core.Controllers" 
                   );

【讨论】:

它有效。注意新的 web.config 文件,它可能会覆盖旧的全局配置。【参考方案3】:

即使它已经被回答 - 这是简短的语法(ASP.net 3、4、5):

routes.MapRoute("redirect all other requests", "*url",
    new 
        controller = "UnderConstruction",
        action = "Index"
        ).DataTokens = new RouteValueDictionary(new  area = "Shop" );

【讨论】:

这对我很有用。我在根目录没有任何控制器,只使用区域。对于 MVC 4,我将其替换为 RouteConfig.cs 中的默认值。谢谢! 我正在使用 MVC4,这对我来说是最简单的解决方案。允许应用程序将特定区域内的索引视图用作站点的“主页”。 此解决方案在未来将不再适用(来自 Asp.Net MVC6 及更高版本)。 @PatrickDesjardins : 有什么理由不支持上述解决方案? @SeriousM 你的回答是常青树。它仍然有帮助。你救了我一个晚上。【参考方案4】:

感谢 Aaron 指出这是关于定位视图,我误解了这一点。

[更新] 我刚刚创建了一个项目,默认情况下将用户发送到一个区域,而不会弄乱任何代码或查找路径:

在 global.asax 中,照常注册:

    public static void RegisterRoutes(RouteCollection routes)
    
        routes.IgnoreRoute("resource.axd/*pathInfo");

        routes.MapRoute(
            "Default",                                              // Route name
            "controller/action/id",                           // URL with parameters
            new  controller = "Home", action = "Index", id = ""  // Parameter defaults,
        );
    

Application_Start()中,请务必使用以下顺序;

    protected void Application_Start()
    
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);
    

在您所在地区注册,使用

    public override void RegisterArea(AreaRegistrationContext context)
    
        context.MapRoute(
            "ShopArea_default",
            "controller/action/id",
            new  action = "Index", id = "", controller = "MyRoute" ,
            new  controller = "MyRoute" 
        );
    

可以在以下位置找到一个示例 http://www.emphess.net/2010/01/31/areas-routes-and-defaults-in-mvc-2-rc/

我真的希望这是你所要求的......

////

我不认为在这种情况下写一个伪ViewEngine 是最好的解决方案。 (缺乏声誉,我无法评论)。 WebFormsViewEngine 是区域感知的,包含 AreaViewLocationFormats,默认情况下定义为

AreaViewLocationFormats = new[] 
        "~/Areas/2/Views/1/0.aspx",
        "~/Areas/2/Views/1/0.ascx",
        "~/Areas/2/Views/Shared/0.aspx",
        "~/Areas/2/Views/Shared/0.ascx",
    ;

我相信你不遵守这个约定。你发了

public ActionResult ActionY() 
 
    return View("~/Areas/AreaZ/views/ActionY.aspx"); 
 

作为一个有效的黑客,但这应该是

   return View("~/Areas/AreaZ/views/ControllerX/ActionY.aspx"); 

如果您不想遵循约定,但是,您可能希望通过从 WebFormViewEngine 派生(例如,在 MvcContrib 中完成)采取一条短路径,您可以在其中设置查找路径构造函数,或者-有点hacky-通过在Application_Start上指定这样的约定:

((VirtualPathProviderViewEngine)ViewEngines.Engines[0]).AreaViewLocationFormats = ...;

当然,这应该更加小心,但我认为它表明了这个想法。这些字段是 MVC 2 RC 中 VirtualPathProviderViewEngine 中的 public

【讨论】:

值得注意的是,这仅适用于 MVC 2 RC - MVC 1 VirtualPathProviderViewEngine 没有此属性,也不是区域感知的。虽然这个问题确实是关于 MVC 2 的,但很多人仍然没有使用它(并且在一段时间内不会使用它)。因此,对于特定问题,您的答案更容易,但我的答案是唯一适用于偶然发现此问题的 MVC1 用户的答案。我喜欢提供不依赖于可能会发生变化的预发布功能的答案。 另外,它不是一个“伪视图引擎”——视图引擎类被故意设计成可扩展的,以便可以使用不同类型的视图。 这不是要侮辱你,对不起。它是“伪”的,因为它不会显着改变视图的处理方式,而只是替换了一些值。 我没有被冒犯,我只是想澄清一个事实,即派生自定义视图引擎并不是一个特别不寻常的原因,相关方法是可覆盖的事实证明了这一点。跨度> 关于RegisterAreasRegisterRoutes 之前的重要提示。想知道为什么我的代码突然停止工作并注意到重构;)【参考方案5】:

我猜您希望用户在访问过~/ URL 后被重定向到~/AreaZ URL。 我将通过您的根目录HomeController 中的以下代码来实现。

public class HomeController

    public ActionResult Index()
    
        return RedirectToAction("ActionY", "ControllerX", new  Area = "AreaZ" );
    

以及Global.asax中的以下路线。

routes.MapRoute(
    "Redirection to AreaZ",
    String.Empty,
    new  controller = "Home ", action = "Index" 
);

【讨论】:

这可行,但它会更改为用户浏览器上的 URL。真的不理想。【参考方案6】:

首先,您使用的是哪个版本的 MVC2?从 preview2 到 RC 发生了重大变化。

假设您使用 RC,我认为您的路线映射应该看起来不同。在您所在地区的AreaRegistration.cs,您可以注册某种默认路由,例如

        context.MapRoute(
            "ShopArea_default",
            "controller/action/id",
            new  action = "Index", id = "", controller="MyRoute" 
        );

默认情况下,上面的代码会将用户发送到我们ShopArea 中的MyRouteController

使用空字符串作为第二个参数会引发异常,因为必须指定控制器。

当然,您必须更改 Global.asax 中的默认路由,这样它就不会干扰此默认路由,例如通过使用主站点的前缀。

另请参阅此线程和 Haack 的回答:MVC 2 AreaRegistration Routes Order

希望这会有所帮助。

【讨论】:

谢谢,但我不确定这是否能解决问题中解释的问题。以及它的 MVC RC【参考方案7】:

将以下内容添加到我的 Application_Start 对我有用,但我不确定您在 RC 中是否有此设置:

var engine = (WebFormViewEngine)ViewEngines.Engines.First();

// These additions allow me to route default requests for "/" to the home area
engine.ViewLocationFormats = new string[]  
    "~/Views/1/0.aspx",
    "~/Views/1/0.ascx",
    "~/Areas/1/Views/1/0.aspx", // new
    "~/Areas/1/Views/1/0.ascx", // new
    "~/Areas/1/Views/0.aspx", // new
    "~/Areas/1/Views/0.ascx", // new
    "~/Views/1/0.ascx",
    "~/Views/Shared/0.aspx",
    "~/Views/Shared/0.ascx"
;

【讨论】:

【参考方案8】:

我为使其正常工作所做的工作如下:

    我在根/Controllers 文件夹中创建了一个默认控制器。我将控制器命名为 DefaultController。

    在控制器中我添加了以下代码:

    namespace MyNameSpace.Controllers 
    public class DefaultController : Controller 
        // GET: Default
        public ActionResult Index() 
            return RedirectToAction("Index", "ControllerName", new area = "FolderName");
        
     
    

    在我的 RouterConfig.cs 中,我添加了以下内容:

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

这一切背后的诀窍是我创建了一个默认构造函数,每次我的应用程序启动时它始终是启动控制器。当它点击该默认控制器时,它将重定向到我在默认索引操作中指定的任何控制器。在我的情况下是

www.myurl.com/FolderName/ControllerName

.

【讨论】:

【参考方案9】:
routes.MapRoute(
                "Area",
                "area/",
                new  area = "AreaZ", controller = "ControlerX ", action = "ActionY " 
            );

你试过了吗?

【讨论】:

是的,问题在于现在该站点在根目录中查找视图。未找到视图“ActionY”或其主视图。搜索了以下位置:~/Views/ActionY/ActionY.aspx ~/Views/ActionY/ActionY.ascx ~/Views/Shared/ActionY.aspx ~/Views/Shared/ActionY.ascx 我明白了。我将尝试找到解决方案。为问题 +1【参考方案10】:

定位不同的构建块是在请求生命周期中完成的。 ASP.NET MVC 请求生命周期中的第一步是将请求的 URL 映射到正确的控制器操作方法。这个过程称为路由。默认路由在 Global.asax 文件中初始化,并向 ASP.NET MVC 框架描述如何处理请求。双击MvcApplication1项目中的Global.asax文件会显示如下代码:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing;

namespace MvcApplication1 

   public class GlobalApplication : System.Web.HttpApplication
   
       public static void RegisterRoutes(RouteCollection routes)
       
           routes.IgnoreRoute("resource.axd/*pathInfo");

           routes.MapRoute(
               "Default",                                          // Route name
               "controller/action/id",                       // URL with parameters
               new  controller = "Home", action = "Index",
                     id = ""   // Parameter defaults
           );

       

       protected void Application_Start()
       
           RegisterRoutes(RouteTable.Routes);
       
   


在 Application_Start() 事件处理程序中,每当编译应用程序或重新启动 Web 服务器时都会触发该事件处理程序,它会注册一个路由表。默认路由名为 Default,并以 http://www.example.com/controller/action/id 的形式响应 URL。 和 之间的变量使用请求 URL 中的实际值填充,如果 URL 中没有覆盖,则使用默认值填充。此默认路由将根据默认路由参数映射到 Home 控制器和 Index 操作方法。我们不会对这个路由图进行任何其他操作。

默认情况下,所有可能的 URL 都可以通过此默认路由进行映射。也可以创建我们自己的路线。例如,让我们将 URL http://www.example.com/Employee/Maarten 映射到 Employee 控制器、Show 操作和 firstname 参数。下面的代码 sn -p 可以插入到我们刚刚打开的 Global.asax 文件中。因为ASP.NET MVC框架使用的是第一个匹配路由,所以这段代码sn -p应该插入到默认路由上面;否则该路由将永远不会被使用。

routes.MapRoute(

   "EmployeeShow",                    // Route name
   "Employee/firstname",            // URL with parameters
    new                              // Parameter defaults
       controller = "Employee",
       action = "Show", 
       firstname = "" 
     

);

现在,让我们为这条路线添加必要的组件。首先,在 Controllers 文件夹中创建一个名为 EmployeeController 的类。您可以通过向项目中添加一个新项目并选择位于 Web | 下的 MVC 控制器类模板来完成此操作。 MVC 类别。删除 Index 操作方法,并将其替换为名为 Show 的方法或操作。此方法接受 firstname 参数并将数据传递到 ViewData 字典。视图将使用该字典来显示数据。

EmployeeController 类会将一个 Employee 对象传递给视图。这个 Employee 类应该被添加到 Models 文件夹中(右键单击这个文件夹,然后从上下文菜单中选择 Add | Class)。这是 Employee 类的代码:

namespace MvcApplication1.Models 

   public class Employee
   
       public string FirstName  get; set; 
       public string LastName  get; set; 
       public string Email  get; set; 
   

 

【讨论】:

谢谢,不过我不太确定这与设置默认区域有何关系。 :-/【参考方案11】:

好吧,虽然创建自定义视图引擎可以解决这个问题,但您仍然可以有其他选择:

决定您需要默认显示的内容。 那个东西有控制器和动作(和区域),对吧? 打开该区域注册并添加如下内容:
public override void RegisterArea(AreaRegistrationContext context)

    //this makes it work for the empty url (just domain) to act as current Area.
    context.MapRoute(
        "Area_empty",
        "",
        new  controller = "Home", action = "Index", id = UrlParameter.Optional ,
        namespaces: new string[]  "Area controller namespace" 
    );
        //other routes of the area

干杯!

【讨论】:

同意。虽然我认为这个路由定义更合适的地方是在 Global.asax 文件中。 在这种情况下,您的 global.asax 定义会知道区域控制器命名空间的存在,我认为这是不对的。区域是一项附加功能,这意味着您必须能够在不触及 global.asax 定义的情况下添加/删除一个。在我解决这个问题的方法中,我更喜欢一个区域来“接管”请求,而不是一个 [全球] 网站来“移交”请求。【参考方案12】:

这个问题的公认解决方案是,虽然在总结如何创建自定义视图引擎方面是正确的,但没有正确回答这个问题。这里的问题是 Pino 错误地指定了他的默认路线。特别是他的“区域”定义是不正确的。 “区域”是通过 DataTokens 集合检查的,应该这样添加:

var defaultRoute = new Route("",new RouteValueDictionary()"controller","Default","action","Index",null/*constraints*/,new RouteValueDictionary()"area","Admin",new MvcRouteHandler());
defaultRoute.DataTokens.Add("Namespaces","MyProject.Web.Admin.Controller"); 
routes.Add(defaultRoute);

默认对象中指定的“区域”将被忽略。上面的代码创建了一个默认路由,它捕获对您站点根目录的请求,然后调用默认控制器,管理区域中的索引操作。另请注意将“命名空间”键添加到 DataTokens,仅当您有多个具有相同名称的控制器时才需要。此解决方案已通过 Mvc2 和 Mvc3 .NET 3.5/4.0 验证

【讨论】:

【参考方案13】:

ummm,我不知道为什么要这么编程,我认为通过指定这个默认路由很容易解决原来的问题......

routes.MapRoute("Default", "*id", 
                 new  controller = "Home"
                     , action = "Index"
                     , id = UrlParameter.Optional 
                     
              );

【讨论】:

以上是关于如何在 MVC 中设置默认路由(到某个区域)的主要内容,如果未能解决你的问题,请参考以下文章

在 React/Material ui 路由中设置默认活动选项卡

cisco设备如何在RIPv2协议中设置默认路由?

如何使用 asp.net mvc 中的标记在 Select2 输入中设置默认值

MVC3:在“仅代码”中设置默认值

在 ASP.NET MVC 中设置默认 JSON 序列化程序

如何从下拉列表中设置默认值[重复]