几天前,我们开始在ASP.NET MVC应用程序的Elmah错误日志中收到以下错误:
堆栈不足以安全地继续执行程序。这个可以 因为在调用堆栈或函数上有太多函数而发生 堆栈使用了太多的堆栈空间。
有问题的应用程序是在Web场中的2台Windows Server 2012服务器上运行的多租户Web应用程序。在任一服务器上定期(每小时1或2次)发生错误,但始终在同一租户URL上。我们已经设置了具有相同设置(主题等)的另一个租户,但无法复制错误。它从未发生过。
异常和堆栈跟踪表明正在执行某种递归函数。在堆栈跟踪的开头:
System.Web.HttpException(0x80004005):执行处理程序的子请求时出错 'System.Web.Mvc.HttpHandlerUtil + ServerExecuteHttpHandlerAsyncWrapper'。 ---> System.Web.HttpException(0x80004005):执行处理程序的子请求时出错 'System.Web.Mvc.HttpHandlerUtil + ServerExecuteHttpHandlerAsyncWrapper'。 --->
在我们到达调用堆栈中的下一个项目之前,这会重复85次。
然后我们有以下内容:
at System.Runtime.CompilerServices.RuntimeHelpers.EnsureSufficientExecutionStack()
at System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag)
at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
at System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag)
at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout)
at System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.Wrap[TResult](Func`1 func)
at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage)
at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
at System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter)
at System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues)
at ASP._Page_Themes_Clik_Views_Shared__Layout_cshtml.Execute() in c:\MySite\wwwroot\Themes\Clik\Views\Shared\_Layout.cshtml:line 15
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
at System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body)
at System.Web.WebPages.WebPageBase.PopContext()
at StackExchange.Profiling.MVCHelpers.ProfilingViewEngine.WrappedView.Render(ViewContext viewContext, TextWriter writer)
at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.<>c__DisplayClass4.<Wrap>b__3()
at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.Wrap[TResult](Func`1 func)
at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage)
at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
at System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter)
at System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues)
at ASP._Page_Themes_Clik_Views_Shared__Layout_cshtml.Execute() in c:\MySite\wwwroot\Themes\Clik\Views\Shared\_Layout.cshtml:line 15
来自:
的堆栈跟踪at ASP._Page_Themes_Clik_Views_Shared__Layout_cshtml.Execute()in c:\ MySite \ wwwroot \ Themes \ Clik \ Views \ Shared_Layout.cshtml:第15行
在System.Web.WebPages.WebPageBase.ExecutePageHierarchy()at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
同样重复85次,好像视图是递归执行的。
它指向的代码行是对Html.Action
的调用:
public MvcHtmlString Menu(string name, string overrideView = null)
{
Ensure.Argument.NotNullOrEmpty(name, "name");
return html.Action("_details", "menus", new { name = name, viewName = overrideView });
}
这与显示网站导航菜单的所有其他租户和主题使用的代码相同。 MenusController
:
[HttpGet]
public async Task<ActionResult> Details(string name)
{
var menu = await menusClient.GetMenuByName(
siteId: siteContext.SiteId,
name: name
)
.ConfigureAwait(false);
if (menu == null)
{
return HttpNotFound();
}
var model = Mapper.Map<MenuDetailsModel>(menu);
model.SetCurrentMenuItem(Request.Url);
return View("Details", model);
}
#region Widget
[HttpGet, ChildActionOnly]
public ActionResult _Details(string name)
{
return Details(name).Result; // this is converted to a partial view result by an action filter
}
由于ASP.NET MVC不支持异步子操作,因此我们必须在_Details
中对我们的异步操作进行阻塞调用。请注意,我们有一个操作过滤器,负责将ViewResult从Details
转换为PartialViewResult
。
正如我所说,这段代码在开发和生产(几乎所有时间)中都能正常工作。我试过在MenusController
内抛出异常,但我仍然无法复制异常。
答案 0 :(得分:0)
试试这个:
public static MvcHtmlString Menu(this HtmlHelper helper, string name, string overrideView = null)
{
var url = new UrlHelper(htmlHelper.ViewContext.RequestContext);
Ensure.Argument.NotNullOrEmpty(name, "name");
return url.Action("_details", "menus", new { name = name, viewName = overrideView });
}