@Html.Action 和同名的控制器
@Html.Action and Controllers with same name
在为 MVC 站点创建插件时,我遇到了有关控制器解析的问题。
以下是与当前上下文相关的所有路由:
routes.MapRoute("Route1",
"Admin/Product/{action}/{id}",
new { controller = "Product", action = "Index", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
routes.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", area = "Admin", id = "" },
new[] { "Admin.Controllers" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "Public.Controllers" }
);
整个解决方案中有3个ProductController 类 :
- Plugin.Controllers.ProductController(继承自管理员)
- Admin.Controllers.ProductController
- Public.Controllers.ProductController
在我看来“/Views/Home/Index.cshtml”(即没有任何区域的 HomeController 的 "Index" 动作)我有以下代码:
@Html.Action("HomepageProducts", "Product")
指的是Public.Controllers.ProductController.
的动作"HomepageProducts"
MVC 查找插件控制器而不是 public 并抛出以下异常:
[HttpException (0x80004005): A public action method 'HomepageProducts' was not found on controller 'Plugin.Controllers.ProductController'.]
System.Web.Mvc.Controller.HandleUnknownAction(String actionName) +291
System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +31
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +49
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) +12
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +22
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +49
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +49
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.Mvc.<>c__DisplayClassa.b__9() +22
System.Web.Mvc.<>c__DisplayClass4.b__3() +10
System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +27
[HttpException (0x80004005): Execution of the child request failed. Please examine the InnerException for more information.]
System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +102
System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Action action) +64
System.Web.Mvc.ServerExecuteHttpHandlerAsyncWrapper.EndProcessRequest(IAsyncResult result) +71
System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +1436
[HttpException (0x80004005): Erreur d'exécution de la demande enfant pour le gestionnaire 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.]
System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +3428452
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) +76
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +29
System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +24
System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) +464
System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues) +83
System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName) +10
ASP._Page_Views_Home_Index_cshtml.Execute() in c:\Path\To\My\Project\Views\Home\Index.cshtml:14
如果这有帮助,解决方案使用 Autofac.MVC5...
欢迎任何 help/comment/idea。
我是不是遗漏了什么,或者控制器解析中只隐含了路由?
更新
浏览 "Admin" 区域时,所有操作均正常执行,插件和管理控制器工作正常。
如果我评论插件路由,就不会再抛出错误了。当然我的插件控制器不再被调用了。
// routes.MapRoute("Route1",
// "Admin/Product/{action}/{id}",
// new { controller = "Product", action = "Index", area = "Admin", id = UrlParameter.Optional },
// new[] { "Plugin.Controllers" }
// )
所以我猜问题是由于插件路由、插件控制器本身或 MVC 解析路由的方式引起的?
更新 2
我试图取消注释所有路线并在@Html.Action() 中指定区域如下:
@Html.Action("HomepageProducts", "Product", new { area = "" })
但是 MVC 忽略该区域并尝试加载插件控制器...
[HttpException (0x80004005): A public action method 'HomepageProducts' was not found on controller 'Plugin.Controllers.ProductController'.]
我确定我错过了一些东西,但我通过注册每个 Plugin.ProductController 我从管理员覆盖的操作路线来绕过我的问题。
routes.MapRoute("Route1",
"Admin/Product/{action}/{id}",
new { controller = "Product", action = "Index", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
//...becomes...
routes.MapRoute("Product.Action1",
"Admin/Product/Action1/{id}",
new { controller = "Product", action = "Action1", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
routes.MapRoute("Product.Action2",
"Admin/Product/Action2/{id}",
new { controller = "Product", action = "Action2", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
//...
现在一切正常。有了这个,我就可以派生出控制器了。
在为 MVC 站点创建插件时,我遇到了有关控制器解析的问题。
以下是与当前上下文相关的所有路由:
routes.MapRoute("Route1",
"Admin/Product/{action}/{id}",
new { controller = "Product", action = "Index", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
routes.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", area = "Admin", id = "" },
new[] { "Admin.Controllers" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "Public.Controllers" }
);
整个解决方案中有3个ProductController 类 :
- Plugin.Controllers.ProductController(继承自管理员)
- Admin.Controllers.ProductController
- Public.Controllers.ProductController
在我看来“/Views/Home/Index.cshtml”(即没有任何区域的 HomeController 的 "Index" 动作)我有以下代码:
@Html.Action("HomepageProducts", "Product")
指的是Public.Controllers.ProductController.
的动作"HomepageProducts"MVC 查找插件控制器而不是 public 并抛出以下异常:
[HttpException (0x80004005): A public action method 'HomepageProducts' was not found on controller 'Plugin.Controllers.ProductController'.] System.Web.Mvc.Controller.HandleUnknownAction(String actionName) +291 System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +31 System.Web.Mvc.Async.WrappedAsyncVoid
1.CallEndDelegate(IAsyncResult asyncResult) +29 System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +49 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36 System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) +12 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +22 System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +49 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26 System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10 System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +29 System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +49 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9 System.Web.Mvc.<>c__DisplayClassa.b__9() +22 System.Web.Mvc.<>c__DisplayClass4.b__3() +10 System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +27[HttpException (0x80004005): Execution of the child request failed. Please examine the InnerException for more information.] System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +102 System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Action action) +64 System.Web.Mvc.ServerExecuteHttpHandlerAsyncWrapper.EndProcessRequest(IAsyncResult result) +71 System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +1436
[HttpException (0x80004005): Erreur d'exécution de la demande enfant pour le gestionnaire 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.] System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +3428452 System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) +76 System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +29 System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +24 System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) +464 System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues) +83 System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName) +10 ASP._Page_Views_Home_Index_cshtml.Execute() in c:\Path\To\My\Project\Views\Home\Index.cshtml:14
如果这有帮助,解决方案使用 Autofac.MVC5... 欢迎任何 help/comment/idea。
我是不是遗漏了什么,或者控制器解析中只隐含了路由?
更新
浏览 "Admin" 区域时,所有操作均正常执行,插件和管理控制器工作正常。
如果我评论插件路由,就不会再抛出错误了。当然我的插件控制器不再被调用了。
// routes.MapRoute("Route1",
// "Admin/Product/{action}/{id}",
// new { controller = "Product", action = "Index", area = "Admin", id = UrlParameter.Optional },
// new[] { "Plugin.Controllers" }
// )
所以我猜问题是由于插件路由、插件控制器本身或 MVC 解析路由的方式引起的?
更新 2
我试图取消注释所有路线并在@Html.Action() 中指定区域如下:
@Html.Action("HomepageProducts", "Product", new { area = "" })
但是 MVC 忽略该区域并尝试加载插件控制器...
[HttpException (0x80004005): A public action method 'HomepageProducts' was not found on controller 'Plugin.Controllers.ProductController'.]
我确定我错过了一些东西,但我通过注册每个 Plugin.ProductController 我从管理员覆盖的操作路线来绕过我的问题。
routes.MapRoute("Route1",
"Admin/Product/{action}/{id}",
new { controller = "Product", action = "Index", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
//...becomes...
routes.MapRoute("Product.Action1",
"Admin/Product/Action1/{id}",
new { controller = "Product", action = "Action1", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
routes.MapRoute("Product.Action2",
"Admin/Product/Action2/{id}",
new { controller = "Product", action = "Action2", area = "Admin", id = UrlParameter.Optional },
new[] { "Plugin.Controllers" }
)
//...
现在一切正常。有了这个,我就可以派生出控制器了。