3

我有以下情况:

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(String operationType) 在 Microsoft.Reporting.WebForms.HttpHandler.ProcessRequest(HttpContext context) 在 >System.Web.HttpApplication.CallHandlerExecutionStep .System.Web.HttpApplication.IExecutionS>tep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& >completedSynchronously)

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

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

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

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

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

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

4

2 回答 2

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;
        }
    }
}
于 2010-08-11T12:04:43.303 回答
0

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

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

于 2010-08-03T19:59:35.437 回答