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

发布于 2024-09-11 18:31:42 字数 1937 浏览 4 评论 0原文

我遇到以下情况:

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 异常消息:Die ASP.NET-Sitzung ist abgelaufen oder konnte nicht gefunden >werden。 在 Microsoft.Reporting.WebForms.ViewerDataOperation..ctor() 在 Microsoft.Reporting.WebForms.HttpHandler.GetHandler(字符串操作类型) 在 Microsoft.Reporting.WebForms.HttpHandler.ProcessRequest(HttpContext 上下文) >System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionS>tep.Execute() 在 System.Web.HttpApplication.ExecuteStep(IExecutionStep 步骤,Boolean>completedSynchronously)

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

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

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

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

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

我可以在哪里处理错误而不终止工作进程,或者获取报告以使用状态服务器?

I have the following situation:

Microsoft Report Viewer 2010 is used to display reports (.rdlc files) in local mode in an ASP.NET web application. The report data is supplied by assigning a datasource in the code behind of an ASPX page. Here's an example:

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);
}

Normally this works great, every report we have loads just fine.

When I leave the page open until the worker process recycles, then try to refresh the report or do any kind of postback on the report page, I get an (unhandled) exception "ASP.NET Session has expired".

Exception information:
Exception type: AspNetSessionExpiredException
Exception message: Die ASP.NET-Sitzung ist abgelaufen oder konnte nicht gefunden >werden.
at Microsoft.Reporting.WebForms.ViewerDataOperation..ctor()
at Microsoft.Reporting.WebForms.HttpHandler.GetHandler(String operationType)
at Microsoft.Reporting.WebForms.HttpHandler.ProcessRequest(HttpContext context)
at >System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionS>tep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& >completedSynchronously)

IIS is set to recycle every morning at 5 a.m. We use the InProc setting in the web.config, so obviously, the session is lost. If I understand the ASP.NET behaviour correctly, the unhandled exception should cause the worker process to terminate. There should be a new worker process when the next request arrives.

If the session timeout setting is low, it causes the same exception. This seems odd, because from what I read, the Report Viewer should ping the server to keep the session alive.

I tried to catch the exception, but it is thrown somewhere inside the ReportViewer control, before I get to access it in page load. The code above is still executed if I take out the IsPostBack, but it has no effect.

I tried using state server instead of keeping the session in the process, so it would not lose it's session, but this leads to other errors from the report viewer. It seemed to be unable to store it's session data in the state server.

The environment is Windows Server 2003
.NET 4.0
Report Viewer 2010

Where can I either handle the error, without having the worker process terminate, or get the report to use stateserver?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽袖吟 2024-09-18 18:31:42

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

我还使用了一个脚本来保持会话处于活动状态,因为报表查看器本身不会执行此操作。但由于我对会话检查感到满意,所以我禁用了它。

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;
        }
    }
}

I now solved it, by using a custom page derived from the base page class. I now check if the session is new, then redirect to the same page, thereby reloading the report from scratch.

I also used a script to keep the session alive, since the report viewer is not doing this by itself. But since I'm satisfied with the session check, I disabled it.

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;           
    }
}

The keep-alive-script calls an http handler (.ashx file) that touches the session every time it's called (not sure actually if this is necessary). Here it is for the record:

 public class KeepSessionAlive : IHttpHandler, IRequiresSessionState
{

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

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}
甜尕妞 2024-09-18 18:31:42

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

我遇到了同样的问题,为我解决的方法是 A) 设置回收的特定时间(您已经拥有)和 B) 将工作进程限制为最多 1在应用程序池设置中

Have you tried limiting the number of worker processes to 1?

I was having the same issue, and what fixed it for me was A) setting a specfic time of day for recycle (which you already have) and B) limit worker processes to max of 1 in app pool settings.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文