MVC HTML.RenderAction – Error: Duration must be a

2019-03-24 07:23发布

On my website I want the user to have the ability to login/logout from any page. When the user select login button a modal dialog will be present to the user for him to enter in his credentials.

Since login will be on every page, I thought I would create a partial view for the login and add it to the layout page. But when I did this I got the following error: Exception Details: System.InvalidOperationException: Duration must be a positive number.

There are other ways to work around this that would not using partial views, but I believe this should work.

So to test this, I decided to make everything simple with the following code:

Created a layout page with the following code

@{Html.RenderAction("_Login", "Account");}

In the AccountController:

public ActionResult _Login()
{
    return PartialView("_Login");
}

Partial View _Login

<a id="signin">Login</a>

But when I run this simple version this I still get this error: Exception Details: System.InvalidOperationException: Duration must be a positive number.

Source of error points to "@{Html.RenderAction("_Login", "Account");}"

There are some conversations on the web that are similar to my problem, which identifies this as bug with MVC (see links below). But the links pertain to Caching, and I'm not doing any caching.

OuputCache Cache Profile does not work for child actions
http://aspnet.codeplex.com/workitem/7923

Asp.Net MVC 3 Partial Page Output Caching Not Honoring Config Settings Asp.Net MVC 3 Partial Page Output Caching Not Honoring Config Settings

Caching ChildActions using cache profiles won't work? Caching ChildActions using cache profiles won't work?

I'm not sure if this makes a difference, but I'll go ahead and add it here. I'm using MVC 3 with Razor.


Update
Stack Trace

[InvalidOperationException: Duration must be a positive number.]
   System.Web.Mvc.OutputCacheAttribute.ValidateChildActionConfiguration() +624394
   System.Web.Mvc.OutputCacheAttribute.OnActionExecuting(ActionExecutingContext filterContext) +127
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +72
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +784922
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +314
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +784976
   System.Web.Mvc.Controller.ExecuteCore() +159
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +335
   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +62
   System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +20
   System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +54
   System.Web.Mvc.<>c__DisplayClass4.<Wrap>b__3() +15
   System.Web.Mvc.ServerExecuteHttpHandlerWrapper.Wrap(Func`1 func) +41
   System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +1363

[HttpException (0x80004005): Error executing child request for handler '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) +2419
   System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) +275
   System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +94
   System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) +838
   System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues) +56
   ASP._Page_Views_Shared_SiteLayout_cshtml.Execute() in c:\Projects\prj Projects\prj\Source\Presentation\prj.PublicWebSite\Views\Shared\SiteLayout.cshtml:80
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +280
   System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +104
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +173
   System.Web.WebPages.WebPageBase.Write(HelperResult result) +89
   System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body) +234
   System.Web.WebPages.WebPageBase.PopContext() +234
   System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +384
   System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +33
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +784900
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +784900
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +265
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +784976
   System.Web.Mvc.Controller.ExecuteCore() +159
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +335
   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +62
   System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +20
   System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +54
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +453
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +371

Update
When I Break in Code, it errors at @{Html.RenderAction("_Login", "Account");} with the following exception. The inner exception

Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'.

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.RenderAction(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues)
   at ASP._Page_Views_Shared_SiteLayout_cshtml.Execute() in c:\Projects\prj Projects\prj\Source\Presentation\prj.PublicWebSite\Views\Shared\SiteLayout.cshtml:line 80
   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.Write(HelperResult result)
   at System.Web.WebPages.WebPageBase.RenderSurrounding(String partialViewName, Action`1 body)
   at System.Web.WebPages.WebPageBase.PopContext()
   at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)

enter image description here


Answer Thanks Darin Dimitrov

Come to find out, my AccountController had the following attribute

[System.Web.Mvc.OutputCache(NoStore =true, Duration = 0, VaryByParam = "*")].

I don't believe this should caused a problem, but when I removed the attribute everything worked.

BarDev

4条回答
Juvenile、少年°
2楼-- · 2019-03-24 07:28

In some cases it may be appropriate to just create a second action method, with caching disabled that is called by your primary action.

    /// Use this for normal HTTP requests which need to be cached
    [OutputCache(CacheProfile = "Script")]
    public ContentResult Foo(string id)
    {
        return _Foo(id);
    }

    /// Use this for Html.Action
    public ContentResult _Foo(string id)
    {
        return View();
    }

When you need Html.Action you just call _Foo instead of Foo.

@Html.Action("_Foo", "Bar").ToString();

You can then rely on the parent page to do the caching.


Another way is to just bypass the whole 'CacheProfile' thing for ActionMethod and use my 'DonutCacheAttribute' instead.

The 'CacheProfile' for ActionMethods currently only respects the Duration and varyByParam properties - and this method makes it easy to set different caching durations in debug vs. deployment (assuming you're using XDT transformations).

查看更多
够拽才男人
4楼-- · 2019-03-24 07:45

I got around the problem by creating a custom OutputCache attribute, that manually loads the Duration, VarByCustom and VarByParam from the profile:

public class ChildActionOutputCacheAttribute : OutputCacheAttribute
{
    public ChildActionOutputCacheAttribute(string cacheProfile)
    {
        var settings = (OutputCacheSettingsSection)WebConfigurationManager.GetSection("system.web/caching/outputCacheSettings");
        var profile = settings.OutputCacheProfiles[cacheProfile];
        Duration = profile.Duration;
        VaryByParam = profile.VaryByParam;
        VaryByCustom = profile.VaryByCustom;
    }
}

The advantage of this approach is that you get to still keep all your profiles in just one place in the web.config.

This is also posted in the related question: https://stackoverflow.com/a/13866280/1373170

查看更多
Lonely孤独者°
5楼-- · 2019-03-24 07:46

Adding my comment as answer:

Hmm, that's weird. By reading your question I am ready to bet 5 bucks that you have caching enabled somehow. Try renaming the action, controller. Make sure that the action you are calling is not decorated with the [OutputCache] attribute. Try doing this in a new project that you start from scratch. I am sure you will be able to narrow it down.

查看更多
登录 后发表回答