asp.net-mvc 如何在 MVC 中设置默认路由(到区域)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2140208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set a Default Route (To an Area) in MVC
提问by LiamB
Ok this has been asked before but there is no solid solution out there. So for purpose of myself and others who may find this useful.
好的,以前有人问过这个问题,但没有固定的解决方案。所以为了我自己和其他可能会发现这很有用的人。
In MVC2 (ASP.NET) I want it so when someone navigates to the website, there is a default area specified. So navigating to my site should send you to ControllerX ActionY in AreaZ.
在 MVC2 (ASP.NET) 中,我希望这样当有人导航到网站时,会指定一个默认区域。因此,导航到我的站点应该会将您发送到 AreaZ 中的 ControllerX ActionY。
Using the following route in the Global.asax
在 Global.asax 中使用以下路由
routes.MapRoute(
"Area",
"",
new { area = "AreaZ", controller = "ControllerX ", action = "ActionY " }
);
Now this works as in it does try to serve the correct page. However MVC proceeds to look for the View in the root of the site and not in the Area folder.
现在这可以正常工作,因为它确实尝试提供正确的页面。但是 MVC 继续在站点的根目录中而不是在 Area 文件夹中查找视图。
Is there a way to resolve this?
有没有办法解决这个问题?
EDIT
编辑
There is a 'Solution' and that is in ControllerX, ActionY return the full path of the view. Bit of a hack but it does work. However I'm hoping there is a better solution.
有一个“解决方案”,即在 ControllerX 中,ActionY 返回视图的完整路径。有点黑客,但它确实有效。但是我希望有更好的解决方案。
public ActionResult ActionY()
{
return View("~/Areas/AreaZ/views/ActionY.aspx");
}
Edit:
编辑:
This also becomes an issue when having a HTML ActionLink of the page. If the area is not set the Action Link is output blank.
当拥有页面的 HTML ActionLink 时,这也会成为一个问题。如果该区域未设置,则操作链接输出为空白。
Is all of this by design or a flaw?
这一切是设计还是缺陷?
采纳答案by Aaronaught
This one interested me, and I finally had a chance to look into it. Other folks apparently haven't understood that this is an issue with finding the view, not an issue with the routingitself - and that's probably because your question title indicates that it's about routing.
这个我很感兴趣,我终于有机会研究它。其他人显然不明白这是查找视图的问题,而不是路由本身的问题- 这可能是因为您的问题标题表明它与路由有关。
In any case, because this is a View-related issue, the only way to get what you want is to override the default view engine. Normally, when you do this, it's for the simple purpose of switching your view engine (i.e. to Spark, NHaml, etc.). In this case, it's not the View-creation logic we need to override, but the FindPartialViewand FindViewmethods in the VirtualPathProviderViewEngineclass.
在任何情况下,因为这是一个与视图相关的问题,获得所需内容的唯一方法是覆盖默认视图引擎。通常,当您这样做时,只是为了切换您的视图引擎(即到 Spark、NHaml 等)的简单目的。在这种情况下,我们需要覆盖的不是视图创建逻辑,而是类中的FindPartialView和FindView方法VirtualPathProviderViewEngine。
You can thank your lucky stars that these methods are in fact virtual, because everything else in the VirtualPathProviderViewEngineis not even accessible- it's private, and that makes it veryannoying to override the find logic because you have to basically rewrite half of the code that's already been written if you want it to play nice with the location cache and the location formats. After some digging in Reflector I finally managed to come up with a working solution.
您可以感谢您的幸运星,这些方法实际上是虚拟的,因为其中的所有其他内容VirtualPathProviderViewEngine甚至都无法访问- 它是私有的,这使得覆盖查找逻辑非常烦人,因为您必须基本上重写已经存在的一半代码如果您希望它与位置缓存和位置格式一起使用,则已编写。在对 Reflector 进行了一些挖掘之后,我终于想出了一个可行的解决方案。
What I've done here is to first create an abstract AreaAwareViewEnginethat derives directly from VirtualPathProviderViewEngineinstead of WebFormViewEngine. I did this so that if you want to create Spark views instead (or whatever), you can still use this class as the base type.
我在这里所做的是首先创建一个AreaAwareViewEngine直接从而VirtualPathProviderViewEngine不是WebFormViewEngine. 我这样做是为了如果你想创建 Spark 视图(或其他),你仍然可以使用这个类作为基本类型。
The code below is pretty long-winded, so to give you a quick summary of what it actually does: It lets you put a {2}into the location format, which corresponds to the area name, the same way {1}corresponds to the controller name. That's it! That's what we had to write all this code for:
下面的代码非常冗长,所以为了给你一个它实际做什么的快速总结:它让你把 a{2}放入位置格式,它对应于区域名称,同样的方式{1}对应于控制器名称。就是这样!这就是我们必须为以下所有代码编写的内容:
BaseAreaAwareViewEngine.cs
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;
}
}
Now as stated, this isn't a concrete engine, so you have to create that as well. This part, fortunately, is mucheasier, all we need to do is set the default formats and actually create the views:
如前所述,这不是一个具体的引擎,因此您也必须创建它。幸运的是,这部分要容易得多,我们需要做的就是设置默认格式并实际创建视图:
AreaAwareViewEngine.cs
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);
}
}
Note that we've added few entries to the standard ViewLocationFormats. These are the new {2}entries, where the {2}will be mapped to the areawe put in the RouteData. I've left the MasterLocationFormatsalone, but obviously you can change that if you want.
请注意,我们向标准ViewLocationFormats. 这些是新{2}条目,其中的{2}将映射到area我们放入RouteData. 我已经离开了MasterLocationFormats,但很明显,如果你愿意,你可以改变它。
Now modify your global.asaxto register this view engine:
现在修改您global.asax以注册此视图引擎:
Global.asax.cs
Global.asax.cs
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new AreaAwareViewEngine());
}
...and register the default route:
...并注册默认路由:
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 = "" }
);
}
Now Create the AreaControllerwe just referenced:
现在创建AreaController我们刚刚引用的:
DefaultController.cs (in ~/Controllers/)
DefaultController.cs(在 ~/Controllers/ 中)
public class DefaultController : Controller
{
public ActionResult ActionY()
{
return View("TestView");
}
}
Obviously we need the directory structure and view to go with it - we'll keep this super simple:
显然我们需要目录结构和视图来配合它——我们将保持这个超级简单:
TestView.aspx (in ~/Areas/AreaZ/Views/Default/ or ~/Areas/AreaZ/Views/Shared/)
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.
And that's it. Finally, we're done.
就是这样。 最后,我们完成了。
For the most part, you should be able to just take the BaseAreaAwareViewEngineand AreaAwareViewEngineand drop it into any MVC project, so even though it took a lot of code to get this done, you only have to write it once. After that, it's just a matter of editing a few lines in global.asax.csand creating your site structure.
在大多数情况下,你应该能够只取BaseAreaAwareViewEngine和AreaAwareViewEngine其拖放到任何MVC项目,所以即使它花了很多的代码来完成这件事,你只需要编写一次。之后,只需编辑几行global.asax.cs并创建站点结构即可。
回答by Chris Alderson
This is how I did it. I don't know why MapRoute() doesn't allow you to set the area, but it does return the route object so you can continue to make any additional changes you would like. I use this because I have a modular MVC site that is sold to enterprise customers and they need to be able to drop dlls into the bin folder to add new modules. I allow them to change the "HomeArea" in the AppSettings config.
我就是这样做的。我不知道为什么 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;
Edit: You can try this as well in your AreaRegistration.RegisterArea for the area you want the user going to by default. I haven't tested it but AreaRegistrationContext.MapRoute does sets route.DataTokens["area"] = this.AreaName;for you.
编辑:您也可以在您希望用户默认访问的区域的 AreaRegistration.RegisterArea 中尝试此操作。我还没有测试过,但是 AreaRegistrationContext.MapRoute 会route.DataTokens["area"] = this.AreaName;为你设置。
context.MapRoute(
"Home_Default",
"",
new {controller = "Home", action = "index" },
new[] { "IPC.Web.Core.Controllers" }
);
回答by SeriousM
even it was answered already - this is the short syntax (ASP.net 3, 4, 5):
甚至已经回答了 - 这是简短的语法(ASP.net 3, 4, 5):
routes.MapRoute("redirect all other requests", "{*url}",
new {
controller = "UnderConstruction",
action = "Index"
}).DataTokens = new RouteValueDictionary(new { area = "Shop" });
回答by mnemosyn
Thanks to Aaron for pointing out that it's about locating the views, I misunderstood that.
感谢 Aaron 指出这是关于定位视图,我误解了这一点。
[UPDATE] I just created a project that sends the user to an Area per default without messing with any of the code or lookup paths:
[更新] 我刚刚创建了一个项目,该项目默认将用户发送到一个区域,而不会弄乱任何代码或查找路径:
In global.asax, register as usual:
在 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,
);
}
in Application_Start(), make sure to use the following order;
在Application_Start(),确保使用以下顺序;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
in you area registration, use
在您的区域注册,使用
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"ShopArea_default",
"{controller}/{action}/{id}",
new { action = "Index", id = "", controller = "MyRoute" },
new { controller = "MyRoute" }
);
}
An example can be found at http://www.emphess.net/2010/01/31/areas-routes-and-defaults-in-mvc-2-rc/
一个例子可以在http://www.emphess.net/2010/01/31/areas-routes-and-defaults-in-mvc-2-rc/找到
I really hope that this is what you were asking for...
我真的希望这就是你所要求的......
////
////
I don't think that writing a pseudo ViewEngineis the best solution in this case. (Lacking reputation, I can't comment). The WebFormsViewEngineis Area aware and contains AreaViewLocationFormatswhich is defined per default as
我不认为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",
};
I believe you don't adhere to this convention. You posted
我相信你不遵守这个约定。你发了
public ActionResult ActionY()
{
return View("~/Areas/AreaZ/views/ActionY.aspx");
}
as a working hack, but that should be
作为一个工作黑客,但这应该是
return View("~/Areas/AreaZ/views/ControllerX/ActionY.aspx");
IF you don't want to follow the convention, however, you might want to take a short path by either deriving from the WebFormViewEngine(that is done in MvcContrib, for example) where you can set the lookup paths in the constructor, or -a little hacky- by specifying your convention like this on Application_Start:
但是,如果您不想遵循约定,您可能希望通过从WebFormViewEngine可以在构造函数中设置查找路径的(例如在 MvcContrib 中完成的)派生或 -a little hacky-通过在以下位置指定您的约定Application_Start:
((VirtualPathProviderViewEngine)ViewEngines.Engines[0]).AreaViewLocationFormats = ...;
This should be performed with a little more care, of course, but I think it shows the idea. These fields are publicin VirtualPathProviderViewEnginein MVC 2 RC.
当然,这应该更加小心地执行,但我认为它表明了这个想法。这些字段public中VirtualPathProviderViewEngine的MVC 2 RC。
回答by Anthony Serdyukov
I guess you want user to be redirected to ~/AreaZURL once (s)he has visited ~/URL.
I'd achieve by means of the following code within your root HomeController.
我猜您希望用户在~/AreaZ访问~/URL后被重定向到URL。我将通过您的 root 中的以下代码实现HomeController。
public class HomeController
{
public ActionResult Index()
{
return RedirectToAction("ActionY", "ControllerX", new { Area = "AreaZ" });
}
}
And the following route in Global.asax.
以及以下路线Global.asax。
routes.MapRoute(
"Redirection to AreaZ",
String.Empty,
new { controller = "Home ", action = "Index" }
);
回答by mnemosyn
First, what version of MVC2 are you using? There have been significant changes from preview2 to RC.
首先,您使用的是什么版本的 MVC2?从 preview2 到 RC,发生了重大变化。
Assuming you use the RC, I think you route-mapping should look differently. In the AreaRegistration.csin your area, you can register some kind of default route, e.g.
假设您使用 RC,我认为您的路由映射看起来应该有所不同。在AreaRegistration.cs您所在的地区,您可以注册某种默认路线,例如
context.MapRoute(
"ShopArea_default",
"{controller}/{action}/{id}",
new { action = "Index", id = "", controller="MyRoute" }
);
The code above will send the user to the MyRouteControllerin our ShopAreaper default.
上面的代码会将用户发送到MyRouteController我们的ShopArea默认设置中。
Using an empty string as a second parameter should throw an exception, because a controller must be specified.
使用空字符串作为第二个参数应该会引发异常,因为必须指定控制器。
Of course you will have to change the default route in Global.asaxso it doesn't interfere with this default route, e.g. by using a prefix for the main site.
当然,您必须更改默认路由,Global.asax以便它不会干扰此默认路由,例如通过为主站点使用前缀。
Also see this thread and Haack's answer: MVC 2 AreaRegistration Routes Order
另请参阅此线程和 Haack 的回答:MVC 2 AreaRegistration Routes Order
Hope this helps.
希望这可以帮助。
回答by Derek Hunziker
Adding the following to my Application_Start works for me, although I'm not sure if you have this setting in RC:
将以下内容添加到我的 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"
};
回答by JEuvin
What I did to get this to work is the following:
我为使其工作所做的工作如下:
- I created a default controller in the root/Controllers folder. I named my controller DefaultController.
In the controller I added the following code:
namespace MyNameSpace.Controllers { public class DefaultController : Controller { // GET: Default public ActionResult Index() { return RedirectToAction("Index", "ControllerName", new {area = "FolderName"}); } } }In my RouterConfig.cs I added the following:
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new {controller = "Default", action = "Index", id = UrlParameter.Optional});
- 我在 root/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});
The trick behind all this is that I made a default constructor which will always be the startup controller every time my app starts. When it hits that default controller it will redirect to any controller I specify in the default Index Action. Which in my case is
这一切背后的技巧是,我创建了一个默认构造函数,每次我的应用程序启动时,它始终是启动控制器。当它遇到该默认控制器时,它将重定向到我在默认索引操作中指定的任何控制器。在我的情况下是
www.myurl.com/FolderName/ControllerName
www.myurl.com/FolderName/ControllerName
.
.
回答by nuhusky2003
Accepted solution to this question is, while correct in summing up how to create a custom view engine, does not answer the question correctly. Issue here is that Pino is incorrectly specifying his default route. Particularly his "area" definition is incorrect. "Area" is checked via DataTokens collection and should be added as such:
这个问题的公认解决方案是,虽然总结如何创建自定义视图引擎是正确的,但没有正确回答问题。这里的问题是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);
Specified "area" in defaults object will be ignored. Code above creates a default route, which catches on requests to your site's root and then calls Default controller, Index action in Admin area. Please also note "Namespaces" key being added to DataTokens, this is only required if you have multiple controllers with same name. This solution is verified with Mvc2 and Mvc3 .NET 3.5/4.0
默认对象中指定的“区域”将被忽略。上面的代码创建了一个默认路由,它捕获对站点根目录的请求,然后在管理区域中调用默认控制器、索引操作。另请注意将“命名空间”键添加到 DataTokens,仅当您有多个具有相同名称的控制器时才需要这样做。此解决方案已通过 Mvc2 和 Mvc3 .NET 3.5/4.0 验证
回答by Tengiz
Well, while creating a custom view engine can work for this, still you can have an alternative:
好吧,虽然创建自定义视图引擎可以解决这个问题,但您仍然可以有一个替代方案:
- Decide what you need to show by default.
- That something has controller and action (and Area), right?
- Open that Area registration and add something like this:
- 确定您需要默认显示的内容。
- 那个东西有控制器和动作(和区域),对吧?
- 打开该区域注册并添加如下内容:
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 }
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 }
Cheers!
干杯!

