Search code examples
asp.netasp.net-mvcvb.netdotnetnuke

Control OnLoad never happens, but OnUnload does


I have an aspx page that contains an ascx child control, and I'm finding that the OnLoad handler is never happening on the child ascx control. Actually, no events are happening in the child or parent control, except for the OnUnload event in the child control.

My page is called CrystalViewer.aspx, inheriting from System.Web.UI.Page, with an override for the OnLoadComplete sub. This page contains the CrystalReport.ascx as a child control.

Markup

<div>
  <uc1:CrystalReport id="CrystalReport1" runat="server" />
</div>

My child control is called CrystalReport.ascx, inheriting from PortalModuleBase in the DotNetNuke.Entities.Modules namespace. This child control contains a multiview where the first view lets you select parameters to pass to the report, and the second view contains the CrystalReportViewer.

<asp:View ID="ViwReport" runat="server">
  <CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server" Width="350px" Height="50px" HasCrystalLogo="False" SeparatePages="True" />
</asp:View>

I have overloads for OnLoad, OnUnload, with logging in each of them.

When I navigate to http://localhost/portal/Modules/Reports/CrystalViewer.aspx?data=O%2b3zhvKVeiMG1qKIK6HGm0ONmAKh336xgBBOzfSVwqH%3d locally, I get the following error.

NullReferenceException: Object reference not set to an instance of an object.
  Reports.CrystalReport.OnUnload(EventArgs e) +401
  System.Web.UI.Control.UnloadRecursive(Boolean dispose) +159
  System.Web.UI.Control.UnloadRecursive(Boolean dispose) +322
  System.Web.UI.Control.UnloadRecursive(Boolean dispose) +322
  System.Web.UI.Page.UnloadRecursive(Boolean dispose) +23
  System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +11538542
  System.Web.UI.Page.ProcessRequest() +269
  System.Web.UI.Page.ProcessRequest(HttpContext context) +167
  System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() + 625
  System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +270

This is a snippet of the OnUnload override, showing how far the method gets before blowing up, because the controller variable is Nothing.

Protected Overloads Overrides Sub OnUnload(ByVal e As EventArgs)
  Using Log.UI.Trace("CrystalReport.OnUnload")
    Log.UI.Send("RemoveHandler controller.ReportDocumentChanged, AddressOf ReportDocumentChanged")
    Log.UI.Send("controller", controller)
    RemoveHandler controller.ReportDocumentChanged, AddressOf ReportDocumentChanged
    '^ blows up here on controller.ReportDocumentChanged because controller is Nothing
    '... that is the last log message I see, so I'm sure that is what the error here is from
  End Using
End Sub

I've been comparing the web.config from the client to one that works in dev and they are pretty much identical except for connection strings. I thought there might have been some Crystal Reports configuration we messed up, so we reinstalled it completely and we still get the same error. I'm not sure where to look next, and I'm sort of waiting to hear how it looks after they restart the server so I'm asking this to see if anyone has seen something similar, where the OnLoad events don't fire, but OnUnload does. It just seems so weird that it would be trying to load something when it never loaded it in the first place, and I have no idea why it doesn't load anyway.

Edit: Our CrystalReport class inherits from MvcContainer(Of Controllers.OnDemandReportController), which inherits from DotNetNuke.Entities.Modules.PortalModuleBase

The OnLoad handler of the CrystalReport never fires, so it never calls the base classes OnLoad, so the controller for the CrystalReport class is Nothing, and blows up.


Solution

  • I solved this today by modifying the OnUnload code to call the controller initialization logic, so that it wouldn't get a NullReferenceException, which exposed the root cause of why the OnLoad handlers were never run.

    There was an assembly binding redirect in the web.config, like the following

    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    

    We use Crystal reports, and it was trying to call a method that exists in the 4.0 version of System.Web.Extensions, that doesn't exist in the 3.5 version.

    This is the post that showed me how to fix the error message I was seeing.

    Method 'get_EnableCdn' in type 'System.Web.UI.ScriptManager' from assembly 'System.Web.Extensions' does not have an implementation