views:

360

answers:

3

Good afternoon! I've spent half my day trying to figure this out; hopefully one of you can help.

I have written a limited CMS and am working on allowing content from the CMS to be displayed as interstitial pages within external sites. To do this, I wanted to create a WCF service that would render the appropriate content and return it as a string to be placed into the client page.

However, I've run into a strange behavior. The RadioButtonList and CheckBoxList controls end up throwing a NullReferenceException during RenderControlInternal (obviously not my contribution). All other controls (textboxes, listboxes, dropdowns, custom composite controls) render fine.

I created an ASMX service alongside the WCF service, and cut/pasted the code directly from the WCF service. It renders the controls perfectly.

Any clues why the WCF service selectively causes bombs?

Here is the service method code:

    public string RenderPageContents(int pageId)
    {
        string output = string.Empty;

        SiteBuilder.Page p = new SiteBuilder.Page();
        if (p.Load(pageId))
        {
            foreach (SiteBuilder.PageItem pi in p.Items)
            {
                if (pi.LoadItemDetails(true))
                {
                    // Calls LoadControl from \Bin
                    Web.Controls.Base.BuilderControlBase bcb =
                          Web.Controls.ControlHelper.CreateSiteBuilderControl(
                              @"C:\Development\SitebuilderService\", 
                             pi.ItemDetails);

                    if (bcb != null)
                    {
                        bcb.Configure(pi);
                        output += ControlHelper.RenderControl(ref bcb);
                    }
                }
            }
        }

        return output;
    }

Here is the code for ControlHelper.RenderControl (yes, it's in VB. It lives in another project).

Public Shared Function RenderControl(ByRef ctrl As Controls.Base.BuilderControlBase) _
      As String
    Dim sb As New StringBuilder()
    Dim tw As New StringWriter(sb)
    Dim hw As New HtmlTextWriter(tw)

    ctrl.RenderControl(hw)

    Return sb.ToString()
End Function

The exception message is "Object reference not set to an instance of an object."

Here is a stacktrace of the Exception thrown when WCF is used:

at System.Web.UI.WebControls.RadioButtonList.Render(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) 
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) 
at System.Web.UI.WebControls.TableCell.RenderContents(HtmlTextWriter writer) 
at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) 
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) 
at System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) 
at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
at System.Web.UI.WebControls.Table.RenderContents(HtmlTextWriter writer) 
at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) 
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) 
at System.Web.UI.WebControls.TableCell.RenderContents(HtmlTextWriter writer) 
at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) 
at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) 
at System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) 
at System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) 
at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) 
at System.Web.UI.Control.RenderControl(HtmlTextWriter writer) 
at XXX.ControlHelper.RenderControl(BuilderControlBase& ctrl) 
    in C:\TFS\XXX\Development\XXX\Web\Controls\Builder\Helpers\ControlHelper.vb:line 81 
at XXX.Services.SiteBuilderService.RenderPageContents(Int32 pageId) 
    in C:\TFS\Development\XXX.Web.Services\XXX.Web.Services\SiteBuilderService.svc.cs:line 61
A: 

Does the WCF service return the correct string when called separately? What kind of binding and security do you use for the WCF service? Can you post some configs (server-side, and possibly client side)?

The binding that would be closest to the ASMX legacy service would be basicHttpBinding with basically all security turned off. Are you using that?

If you call the service in e.g. SoapUI - does it return the string in the expected format? Or maybe some tags and/or special characters might get mangled up?

Marc

marc_s
+2  A: 

Have you tried turning on ASP.NET compatibility mode in your WCF configuration? The error is likely related to the HttpContext not being available (though if I may say it, your current approach, while probably workable, is rather ugly :-))

tomasr
I suspect this might be the issue. I opened up System.Web.UI.WebControls.RadioButtonList.Render using .NET Reflector and found this code: "If (Not MyBase.DesignMode AndAlso Not Me.Context.Request.Browser.Tables) Then". Looking into Context, if page.Context is null, it returns HttpContext.Current.
Chris Porter
Chris Porter
A: 

Does the WCF service return the correct string when called separately?

I'm not sure I understand your exact meaning. Separately from what? If I call the business class that does the processing from a test harness, yes it works correctly. When I call it from an ASMX service it works properly. From WCF, radiobutton rendering breaks.

What kind of binding and security do you use for the WCF service?

I'm using basicHttpBinding.

<binding name="BasicHttpBinding_ISiteBuilderService" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="1024000" maxBufferPoolSize="524288" maxReceivedMessageSize="1024000"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="1024000" maxArrayLength="16384"
          maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None"
            realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>


<endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISiteBuilderService" contract="SiteBuilder.ISiteBuilderService" name="BasicHttpBinding_ISiteBuilderService" />

<service behaviorConfiguration="Xxx.SiteBuilderServiceBehavior"
   name="Xxx.Services.SiteBuilderService">
    <endpoint address="" binding="basicHttpBinding" contract="Kaplan.OEC.Services.ISiteBuilderService">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

<behavior name="Xxx.Services.SiteBuilderServiceBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>

If you call the service in e.g. SoapUI - does it return the string in the expected format? Or maybe some tags and/or special characters might get mangled up?

From SoapUI it also fails to render properly, the same error occurs as from WCF.

Again, thanks for your help. I'm stumped!

Excuse me, but who are you? Are you "Chris"?
John Saunders
yes... sorry. the stack overflow interface is boggling me (first question and all). I see "add comment" to this, but i'm unable to edit my original question, or comment on others answers (maybe i posted question anonymously?).tomasr's answer about "ASP.NET compatibility mode" solved the issue and makes perfect sense (I wish I would have thought to use reflector to learn why).