control object is in a read only state

D

Duke

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
 
W

Walter Wang [MSFT]

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 ([email protected], 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.
 
D

Duke

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
 
D

Duke

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
 
W

Walter Wang [MSFT]

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 ([email protected], 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.
 
D

Duke (AN247)

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
 
W

Walter Wang [MSFT]

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 ([email protected], 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.
 
A

Adnan

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top