Link to home
Start Free TrialLog in
Avatar of purplesoup
purplesoupFlag for United Kingdom of Great Britain and Northern Ireland

asked on

ASP.NET ReportViewer SSRS report gets "Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode" error

I've got an asp.net webpage that displays an SSRS ReportViewer report. It works fine, but I need to change our session to SQL instead of inprocess, and now I'm getting the error below.

I've found a webpage that appears to be a solution to the problem:
http://forums.asp.net/t/1848911.aspx/1?ReportViewer+Unable+to+serialize+the+session+state+in+stateserver+and+sqlserver+mode+

However when I make the change suggested - specify ReportServerCredentials - like this:

_reportViewer1.ServerReport.ReportServerCredentials = new ReportServerConnection();

I still get the error, except that my code has processing mode local, whereas in the forum post it has processing mode remote.

I tried changing to remote and I no longer got the error, but the report didn't show. Also I found that just changing it to processing mode remote stops the error - I don't even need to specify ReportServerCredentials.

So can anyone suggest what I might be missing or not doing?
Avatar of Alfred A.
Alfred A.
Flag of Australia image

You need to serialized your objects accessed by the report.   You can serialized an object by setting the [Serializable] attribute into your class.   Something like this below.

[Serializable]
public class Test
{
     //properties and methods, etc., etc.
}

Note:  If there are properties in your serialized class that should not be serialized, you can declare them with [NonSerialized]  attribute.   I hope this helps.
Avatar of purplesoup

ASKER

I'm not clear what objects are accessed by the report - I've copied the code below for what code works with the ReportViewer - I can't see where any objects are being accessed...?

            _reportViewer1 = new ReportViewer();
            ChildControlsPlaceHolder.Controls.Add(_reportViewer1);
            _reportViewer1.AsyncRendering = false; 
            _reportViewer1.SizeToReportContent = true;
            _reportViewer1.ShowWaitControlCancelLink = true;
            _reportViewer1.ShowPrintButton = true;
            _reportViewer1.ShowZoomControl = true;

            _reportViewer1.Height = Height;
            _reportViewer1.Width = Width;
            _reportViewer1.DocumentMapWidth = DocumentMapWidth;
            _reportViewer1.ZoomMode = ZoomMode;
            _reportViewer1.ZoomPercent = ZoomPercent;

            _reportViewer1.BackColor = Color.LightGray;
            _reportViewer1.Visible = true;
            _reportViewer1.ProcessingMode = ProcessingMode.Local;
            _reportViewer1.AsyncRendering = false;  
            _reportViewer1.SizeToReportContent = true;
            _reportViewer1.ShowRefreshButton = false;
            _reportViewer1.ShowExportControls = false;
            _reportViewer1.ShowWaitControlCancelLink = true;
            _reportViewer1.ShowPrintButton = true;
            _reportViewer1.ShowZoomControl = true;

                _reportViewer1.ShowToolBar = true;
                _reportViewer1.ShowPrintButton = true;  // just for completeness
                _reportViewer1.ShowCredentialPrompts = false;
                _reportViewer1.ShowDocumentMapButton = false;
                _reportViewer1.ShowExportControls = false;
                _reportViewer1.ShowFindControls = false;
                _reportViewer1.ShowPageNavigationControls = false;
                _reportViewer1.ShowParameterPrompts = false;
                _reportViewer1.ShowRefreshButton = false;
                _reportViewer1.ShowZoomControl = false;

                _reportViewer1.ShowToolBar = false;

            _reportViewer1.Style.Add("display", "table !important");
            _reportViewer1.Style.Add("margin", "0px");
            _reportViewer1.Style.Add("overflow", "auto !important;");

Open in new window

Ok, just to make it clear, since you are moving from InProc to State Server/SQL Server with your session state, you need to serialized all objects covered by the change in session state and not only within your report but within the website itself.

The error that you get should provide you the offending class/object that needs to be serialized.   If this is not displayed, check the error stack trace.
I'm working on changing the website itself - and I've made progress doing it, the problem here is that Microsoft within the ReportViewer appears to save an object that isn't serializable in session, and I'm trying to work around that problem.

The link I gave explains the problem and gives a solution, but isn't working for me - I think because I'm running locally and not remotely, but I'm not sure of the reason.

What I'm trying to get is a way to work around this Microsoft SSRS ReportViewer problem, not more generally how to change the website.
I had this problem before with an object that I am not able to serialized before and what I did was to force custom serialization.

With the report viewer code, I assume this is within a method in a class.   What you could do is try setup custom serialization using ISerializable by doing the following and adding GetObjectData with no custom serialize action.      

[Serializable]
public class ReportViewerClassTest : ISerializable
{

    void ISerializable.GetObjectData(SerializationInfo oInfo, StreamingContext oContext)
    {
         //any custom serialize action should put into here
         //you can just leave this blank if no custom serialize action
    }
}

Here are some links that explains ISerializable:

http://www.codeproject.com/Articles/24156/Custom-Serialization-Part-2

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable%28v=vs.100%29.aspx

I hope this helps.
I don't think you're getting the problem here. I'm doing custom serialization as needed in other parts of my website, but here I don't have access to the source code - this appears to be something the ReportViewer itself is doing, it isn't a matter of me serializing one of my own classes, it is ReportViewer having a class that it puts in session that isn't serializable.

This problem is explained in the article above.
Ok.  Can you then provide a snapshot of the SerializationException that points to the Assembly that mentions that it is not marked as serializable from the Stack Trace?
By the way,  if a field, variable or property is not possible to serialized, you could try making the ReportViewer object declaration/field not to serialized within your serializable class by doing the following:

[NonSerialized]
ReportViewer _reportViewer1;

I recall I did something similar with an issue in WCF serialization before.   I hope this works.
Here is the exception coming out of the SSRS Report

Server Error in '/iMISMain15' Application.

Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.Web.HttpException: Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode.

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 


[SerializationException: Type 'System.Runtime.Remoting.ServerIdentity' in Assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.]
   System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) +9474853
   System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) +247
   System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() +160
   System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +491
   System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) +388
   System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) +444
   System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) +133
   System.Web.Util.AltSerialization.WriteValueToStream(Object value, BinaryWriter writer) +1762

[HttpException (0x80004005): Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode.]
   System.Web.Util.AltSerialization.WriteValueToStream(Object value, BinaryWriter writer) +1847
   System.Web.SessionState.SessionStateItemCollection.WriteValueToStreamWithAssert(Object value, BinaryWriter writer) +34
   System.Web.SessionState.SessionStateItemCollection.Serialize(BinaryWriter writer) +638
   System.Web.SessionState.SessionStateUtility.Serialize(SessionStateStoreData item, Stream stream) +244
   System.Web.SessionState.SessionStateUtility.SerializeStoreData(SessionStateStoreData item, Int32 initialStreamSize, Byte[]& buf, Int32& length, Boolean compressionEnabled) +67
   System.Web.SessionState.SqlSessionStateStore.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem) +140
   System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs) +807
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +148
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.547

Open in new window

Ok.  From the trace it is pointing to ServerIdentity.   Do you have anything in your code that is similar to this below?

using System.Runtime.Remoting;

//--- Code, Code, Code ----

private ServerIdentity _identity;

If you have then, put the following in the field:

[NonSerialized]
private ServerIdentity _identity;
No, none of my code has any reference to ServerIdentity - I just ran a full search and it came up with nothing.
Ok.  It looks like it is wrapped in one of the objects you are using.   The error you are getting is a result of the existence of non-serializable objects or MarshalByRef objects.    ServerIdentity is not serializable and that is why you need to decorate it with [NonSerialized] if you are using it directly.

For example, DataRows can't be serialized and one way to counteract [Serializable] is to decorate the datarow field declaration with [NonSerialized].

Back tracking a bit, do you use any object under System.Runtime.Remoting?   If you use any at all, can you try isolating them from serialization by decorating them with [NonSerialized]?
Yes we do have some - but I can't see anything linked to the ReportViewer code - I'm not clear how is that going to help?
You have to understand that doing a session type change (i.e. InProc to SQL Server), all objects covered by your web.config needs to be serialized if it can be serialized.  This might not even be a report viewer issue but something else within your website like these System.Runtime.Remoting objects.

Another approach to this is inherit ISerializable in your class that holds instances of System.Runtime.Remoting objects.  Note that any class inheriting ISerializable would make it serializable.  For example,  a DataTable can be serialized because it implements ISerializable.  I hope this helps.
ok thanks I'll have a closer look at the code that uses System.Runtime.Remoting and see if I can spot anything.
This isn't to do with the Remoting code, but here's where I'm at - see if you can think of a good way forward.

I've written a stand-alone SSRS report running with SQL Sessions that works. Within my application running exactly the same code doesn't work - I get the error.

Also, the error only happens when the report has a parameter. If I run a report within my app that doesn't have a parameter, it works fine.

There must be some check within the SSRS code for something that is set in my application, that isn't set in my stand-alone example. Any thoughts?
Ok.  I checked a two-year old project of mine that uses .rdlc within VS2010 MVC3 web site that uses State Server which is hosted in a separate assembly dll project without any serialization and it works fine.  

By the way, if you are using .rdl file instead within a report project in BIDS (VS2008), then it might be a different issue.

Things that you can try:

1.   Put [NonSerialized] on the following in your code for the LocalReport and List<ReportParameter> if you have one.    If you have ReportParameter as well put one into it as well.

For localReport:

[NonSerialized]
LocalReport lReport = new LocalReport();

For Parameters:

[NonSerialized]
List<ReportParameter> parameterList = new List<ReportParameter>();

2.   Move ReportViewer in a different assembly (different project within the same solution) or create a user control with the report viewer in it and remove [Serializable] within this assembly where report viewer logic exists.  In my BIDS (VS 2008) project a long time ago I used a user control ascx and no serialization tags required.   Here is a link that use ascx

http://sdk.episerver.com/commerce/1.1.2/Content/Developers%20Guide/Reporting/Creating%20custom%20reports.htm

I hope this helps.
Thanks for this - I just found something that is possibly helpful.

I have a single stand-alone web page that runs an SSRS report (with parameters). If I put that page within my application folder and run it, I get the error. If I open the page in its own separate application it works fine. Same code, same web page, same report, just a different application.

I even tried copying the web.config from the main app to the test app, still works in the test app. I also checked the app pool was the same for both my stand alone app and the main application.

And remember it is parameters that triggers this - if the report has no parameters it runs fine, it it has parameters we get the error.
ASKER CERTIFIED SOLUTION
Avatar of purplesoup
purplesoup
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yeh it is a sort of fix - but it still seems pretty weird that running the report outside of my main app works and inside doesn't, *and* that running without any parameters works but with a parameter fails, *and* that the fix is to go back to some legacy mode.

Anyway thanks for all your help and suggestions.
"Please state a reason for selecting your own comment as the solution:"

The reason I'm selecting my comment as the solution is because it was the solution.