如何处理报表查看器会话过期的异常

时间:2010-07-29 10:40:00

标签: .net-4.0 reportviewer session-timeout

我有以下情况:

Microsoft Report Viewer 2010用于在ASP.NET Web应用程序中以本地模式显示报表(.rdlc文件)。通过在ASPX页面后面的代码中分配数据源来提供报告数据。这是一个例子:

if(!IsPostBack){
ReportViewer1.Reset();
ReportDataSource reportDataSource = new ReportDataSource();

reportDataSource.Name = "DataContainerType";
reportDataSource.Value = DatasourceOnPage;
reportDataSource.DataSourceId = "DatasourceOnPageID";
reportDataSource.DataMember = "DataSourceView";

ReportViewer1.ProcessingMode = ProcessingMode.Local;
ReportViewer1.LocalReport.DisplayName = "ReportName";
ReportViewer1.LocalReport.ReportEmbeddedResource = "Reportfile.rdlc";
ReportViewer1.LocalReport.DataSources.Add(reportDataSource);
}

通常这很有效,我们收到的每份报告都很好。

当我打开页面直到工作进程回收,然后尝试刷新报表或在报表页面上进行任何类型的回发,我得到(未处理的)异常“ASP.NET会话已过期” 。

  

异常信息:      异常类型:AspNetSessionExpiredException      例外消息:死于ASP.NET-Sitzung ist abgelaufen oder konnte nicht gefunden> werden。     在Microsoft.Reporting.WebForms.ViewerDataOperation..ctor()     在Microsoft.Reporting.WebForms.HttpHandler.GetHandler(String operationType)     在Microsoft.Reporting.WebForms.HttpHandler.ProcessRequest(HttpContext context)     at> System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionS> tep.Execute()     在System.Web.HttpApplication.ExecuteStep(IExecutionStep步,布尔&> completedSynchronously)

IIS设置为每天早上5点回收。我们在web.config中使用InProc设置,显然,会话丢失了。如果我正确理解ASP.NET行为,未处理的异常应该导致工作进程终止。当下一个请求到达时,应该有一个新的工作进程。

如果会话超时设置为低,则会导致相同的异常。这看起来很奇怪,因为根据我的阅读,报告查看器应该ping服务器以使会话保持活动状态。

我试图捕获异常,但在我在页面加载中访问它之前,它被抛出到ReportViewer控件内部。如果我取出IsPostBack,上面的代码仍然执行,但它没有效果。

我尝试使用状态服务器而不是在会话中保持会话,因此它不会丢失会话,但这会导致报表查看器出现其他错误。它似乎无法将其会话数据存储在状态服务器中。

环境是Windows Server 2003 .NET 4.0 Report Viewer 2010

我可以在哪里处理错误,没有工作进程终止,或者让报告使用stateserver?

2 个答案:

答案 0 :(得分:1)

我现在通过使用从基页类派生的自定义页面来解决它。我现在检查会话是否是新的,然后重定向到同一页面,从而从头开始重新加载报告。

我还使用了一个脚本来保持会话处于活动状态,因为报表查看器本身并没有这样做。但由于我对会话检查感到满意,我禁用了它。

public class ReportPage: System.Web.UI.Page
{

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        #region check for lost session
        if (Context.Session != null)
        {
            if (Session.IsNewSession)
            {
                string cookieHeader = Request.Headers["Cookie"];
                if ((null != cookieHeader) && (cookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
                {
                    Response.Redirect(Request.Url.ToString());
                }
            }
        }

        #endregion check for lost session

        #region generate keepsessionalive script 


        StringBuilder sb = new StringBuilder();
        sb.Append("$(function () {setInterval(KeepSessionAlive, " + GetSessionTimeoutInMs() + ");");
        sb.Append("});");
        sb.Append("function KeepSessionAlive() {");
        sb.Append(string.Format("$.post('{0}', null);", ResolveUrl("~/KeepSessionAlive.ashx")));
        sb.Append("};");

        // register on page
         Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "SessionKeepAlive", sb.ToString(), true);

        #endregion generate keepsessionalive script
    }

    private int GetSessionTimeoutInMs()
    {
        return (this.Session.Timeout * 60000) - 10000;           
    }
}

keep-alive-script调用一个http处理程序(.ashx文件),每次调用它时都会触及会话(实际上不确定是否有必要)。这是记录:

 public class KeepSessionAlive : IHttpHandler, IRequiresSessionState
{

    public void ProcessRequest(HttpContext context)
    {
        context.Session["KeepSessionAlive"] = "KeepAlive!";
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

答案 1 :(得分:0)

您是否尝试将工作进程数限制为1?

我遇到了同样的问题,为我解决的问题是A) setting a specfic time of day for recycle(您已经拥有)和B) limit worker processes to max of 1 in app pool settings