control object is in a read only state

Discussion in 'ASP .Net Web Controls' started by Duke, Mar 15, 2007.

  1. Duke

    Duke Guest

    I have an ASP.Net 2 page with a Report Viewer control (sp1) that displays a
    local report. The report uses the results from a SQL Server 2005 stored
    procedure. It was running fine but given that ASP.Net supports asynchronous
    processing I thought I'd make the stored procedure call asynchronous, freeing
    up resources on the web server whilst the slow running stored procedure is
    executing.

    Changing the stored procedure call over to asynchronous was straight forward
    and it runs ok. Once the async code is completed the Page_PreRenderComplete
    event fires at which point I have an ADO.Net DataSet containing my data,
    which I need to set as a ReportDataSource, via...

    ReportViewer1.LocalReport.DataSources.Clear()

    ReportViewer1.LocalReport.DataSources.Add( _
    New ReportDataSource("DataTable1", _reportDS.Tables(0)) )

    The Clear method works, but DataSources.Add generates an exception with the
    message "Viewer control object is in a read only state".

    Any ideas what is causing this and how I can fix it? Running the queries
    asynchronously would be a huge boost to scalability.

    Thanks,
    Andrew
    Duke, Mar 15, 2007
    #1
    1. Advertising

  2. Hi Andrew,

    Do you mean you're using AddOnPreRenderCompleteAsync as this article
    described:

    #Wicked Code: Asynchronous Pages in ASP.NET 2.0 -- MSDN Magazine, October
    2005
    http://msdn.microsoft.com/msdnmag/issues/05/10/WickedCode/


    I cannot seem to be able to reproduce the issue easily on my side to see
    the exception you mentioned. Would you please post more code here? Thanks.

    Sincerely,
    Walter Wang (, remove 'online.')
    Microsoft Online Community Support

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications. If you are using Outlook Express, please make sure you clear the
    check box "Tools/Options/Read: Get 300 headers at a time" to see your reply
    promptly.

    Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
    where an initial response from the community or a Microsoft Support
    Engineer within 1 business day is acceptable. Please note that each follow
    up response may take approximately 2 business days as the support
    professional working with you may need further investigation to reach the
    most efficient resolution. The offering is not appropriate for situations
    that require urgent, real-time or phone-based interactions or complex
    project analysis and dump analysis issues. Issues of this nature are best
    handled working with a dedicated Microsoft Support Engineer by contacting
    Microsoft Customer Support Services (CSS) at
    http://msdn.microsoft.com/subscriptions/support/default.aspx.
    ==================================================

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Walter Wang [MSFT], Mar 16, 2007
    #2
    1. Advertising

  3. Duke

    Duke Guest

    Walter,

    Not that article. I first saw the async code in Fritz Onion's Essential
    ASP.Net 2.0 book. The article in the March 2007 edition of MSDN magazine
    prompted me to try it.


    The line that errors is...
    ReportViewer1.LocalReport.DataSources.Add(New
    ReportDataSource("DataTable1", dsReport.Tables(0)))
    I've tried it in both the EndGetReportData and the Page_PreRenderComplete
    handlers but it didn't help.

    I wondered if there is an issue because the callbacks are running on a
    different thread than the initial page loading thread.


    The web page has Async="True"
    The code behind has...

    'class level privates...
    Private _reportCon As SqlConnection
    Private _reportCmd As SqlCommand

    Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As
    System.EventArgs) Handles MyBase.PreRender

    'rdlStream As System.IO.MemoryStream = <removed for brevity>

    ReportViewer1.Reset()
    ReportViewer1.LocalReport.ReportPath = ""
    ReportViewer1.LocalReport.LoadReportDefinition(rdlStream)
    ReportViewer1.LocalReport.DataSources.Clear()

    Dim task1 As PageAsyncTask = New PageAsyncTask( _
    New BeginEventHandler(AddressOf BeginGetReportData), _
    New EndEventHandler(AddressOf EndGetReportData), _
    New EndEventHandler(AddressOf GetReportDataTimeout), _
    Nothing, False)

    Page.RegisterAsyncTask(task1)

    End Sub

    Function BeginGetReportData(ByVal src As Object, ByVal e As EventArgs, ByVal
    cb As AsyncCallback, ByVal state As Object) As IAsyncResult

    Dim sPrjConStr As String
    sPrjConStr =
    ConfigurationManager.ConnectionStrings("PrjConStr").ConnectionString +
    ";async=true"

    Dim conReport As SqlConnection
    conReport = New SqlConnection(sPrjConStr)
    conReport.Open()

    _reportCon = conReport
    _reportCmd = getCmd_sp_Prj_centres(conReport)

    Return _reportCmd.BeginExecuteReader(cb, state)

    End Function

    Sub EndGetReportData(ByVal ar As IAsyncResult)

    Try
    Dim dsReport As DataSet = New DataSet()
    Dim drReport As SqlDataReader = _reportCmd.EndExecuteReader(ar)

    'new data directly from reader to dataset
    dsReport.Tables.Add("DataTable1")
    dsReport.Tables(0).Load(drReport)

    'close reader and connection
    drReport.Close()
    _reportCon.Close()

    '--------------------------------------------------
    ' data sources THIS IS THE LINE THAT ERRORS
    ReportViewer1.LocalReport.DataSources.Add(New
    ReportDataSource("DataTable1", dsReport.Tables(0)))

    Finally
    If _reportCon.State = ConnectionState.Open Then
    _reportCon.Close()
    End If
    End Try

    End Sub


    Sub GetReportDataTimeout(ByVal ar As IAsyncResult)
    'operation timed out, so just clean up by closing connection
    If _reportCon.State = ConnectionState.Open Then
    _reportCon.Close()
    End If

    Me.lblReportError.Text = "Query timed out..."
    End Sub

    Protected Sub Page_PreRenderComplete(ByVal sender As Object, ByVal e As
    System.EventArgs) Handles Me.PreRenderComplete
    'All async tasks have completed
    End Sub

    Thanks,
    Andrew
    Duke, Mar 16, 2007
    #3
  4. Duke

    Duke Guest

    Walter,

    I've created a cut down web site running against Northwind that demonstrates
    the problem. It works when synchronous, but fails when asynchronous.
    It is a 10K zip file. How can I send it to you?

    Andrew
    Duke, Mar 16, 2007
    #4
  5. Duke

    Duke Guest

    I originally posted this problem in forums.microsoft.com but as I didn't get
    a response though I'd try the managed newsgroups. The original post has now
    had a response, see...

    http://forums.microsoft.com/MSDN/showpost.aspx?postid=1354152&siteid=1

    ....which suggests the ReportViewer state is locked down once its PreRender
    finishes, which is of course before the asynchronous processing events start.
    Duke, Mar 16, 2007
    #5
  6. Hi Andrew,

    I came to the same conclusion: regardless the async stuff here, just simply
    handle the Page's PreRenderComplete event and change the
    ReportViewer.LocalReport there, you will see the exception.

    After digging into ReportViewer's source code using Reflector
    (http://www.aisto.com/roeder/dotnet/), I can see the
    ReportViewer.OnPreRender sets an internal flag:

    this.m_lockChanges = true;


    And then in its OnReportChanged:

    if (this.m_lockChanges)
    {
    throw new InvalidOperationException(Errors.ReadOnlyViewer);
    }


    Given that the asynchronous page execution model always starts from
    PreRenderComplete in ASP.NET, I'm afraid it's difficult to bypass this
    restriction here.

    The only workaround I can figure out is to dynamically creating the
    ReportViewer on the fly and add to control tree. Do you think it's
    acceptable for you?

    Regards,
    Walter Wang (, remove 'online.')
    Microsoft Online Community Support

    ==================================================
    When responding to posts, please "Reply to Group" via your newsreader so
    that others may learn and benefit from your issue.
    ==================================================

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Walter Wang [MSFT], Mar 16, 2007
    #6
  7. Duke

    Duke (AN247) Guest

    Thanks Walter.

    Creating a ReportViewer control instance once the async code returns and
    adding it to the page's control collection does work. But I was concerned
    that in the case of a series of drill through reports I'd lose the path
    history. I'll look at that method a bit more.

    Would you be able to pass this issue on to the ReportViewer control people.
    Not for comment, but maybe they could think about it for a future release.

    Many thanks for your help,
    Andrew
    Duke (AN247), Mar 16, 2007
    #7
  8. Hi Andrew,

    Thanks for your feedback. I will help forward to appropriate team.

    I understand your concern about the dynamically created ReportViewer
    control might loose its state when posted back. The workaround is based on
    my personal research and not fully tested. If you do find issues in later
    stage, please let me know. Thanks.

    Regards,
    Walter Wang (, remove 'online.')
    Microsoft Online Community Support

    ==================================================
    When responding to posts, please "Reply to Group" via your newsreader so
    that others may learn and benefit from your issue.
    ==================================================

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Walter Wang [MSFT], Mar 18, 2007
    #8
  9. Duke

    Adnan Guest

    Hi Walter and Andrew
    I've had the exact same problem and followed the solution which worked.

    I have a gridview and a reportviewer on my webpage where the reportviewer
    queries runs asynchronusly.

    However the page does not return and display the rest of controls until the
    Asynchornus calls have run. I thought using an asynchornous approch would
    mean all controls including the Gridview are viewable and clickable where as
    the reportviewer will be rendered only when the query has run (which takes 1
    min).

    Is there a way in which I can enable all the other controls to be viewable
    while the reportviewer asynch calls are still running ?

    Thanks
    A


    "Walter Wang [MSFT]" wrote:

    > Hi Andrew,
    >
    > Thanks for your feedback. I will help forward to appropriate team.
    >
    > I understand your concern about the dynamically created ReportViewer
    > control might loose its state when posted back. The workaround is based on
    > my personal research and not fully tested. If you do find issues in later
    > stage, please let me know. Thanks.
    >
    > Regards,
    > Walter Wang (, remove 'online.')
    > Microsoft Online Community Support
    >
    > ==================================================
    > When responding to posts, please "Reply to Group" via your newsreader so
    > that others may learn and benefit from your issue.
    > ==================================================
    >
    > This posting is provided "AS IS" with no warranties, and confers no rights.
    >
    >
    >
    Adnan, Jul 24, 2007
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. vnssoftware
    Replies:
    4
    Views:
    458
    Dmitry R
    Dec 31, 2003
  2. keithb
    Replies:
    2
    Views:
    7,990
    keithb
    Jun 7, 2006
  3. Phillip Vong

    VS2005 - Run Code only in Read Only mode.

    Phillip Vong, Apr 6, 2007, in forum: ASP .Net
    Replies:
    0
    Views:
    317
    Phillip Vong
    Apr 6, 2007
  4. Thomas Guettler
    Replies:
    1
    Views:
    294
    Peter Otten
    Nov 25, 2009
  5. Replies:
    7
    Views:
    3,455
    Vince Xu [MSFT]
    Dec 17, 2009
Loading...

Share This Page