Any DataPortalException lost in WCF portal (connection forcibly closed)

Any DataPortalException lost in WCF portal (connection forcibly closed)

Old forum URL: forums.lhotka.net/forums/t/12852.aspx


swegele posted on Saturday, March 21, 2015

Hi guys,

Anyone experienced this?  I know its a setting I am missing somewhere.  I have a windows forms client.  Solid and working well 2 tier.  Just starting testing in 3 tier mode. 

Everything works great!!  ....that is until there is a server side error.  Instead of ending up with a DataPortalException on the client...I get a sockets error saying the "connection was forcibly closed" and that is it.  Where did my exception go?  I assume this is some setting in IIS 7 or in the config of the endpoint?

Server 2008 R2 & IIS7, Visual Studio 2013 and .NET 4.5, and CSLA 4.5.600

Here is my config.

  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
      <service name="Csla.Server.Hosts.WcfPortal" behaviorConfiguration="returnFaults">
        <endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBinding_IWcfPortal"
                  contract="Csla.Server.Hosts.IWcfPortal" />

        <!-- Add the following endpoint.  -->
        <!-- Note: your service must have an http base address to add this endpoint. -->
        <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
      </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="basicHttpBinding_IWcfPortal" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"
                 maxBufferSize="2147483647">
          <readerQuotas maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647"
                        maxNameTableCharCount="2147483647" maxDepth="2147483647" />
        </binding>
      </basicHttpBinding>
      <wsHttpBinding>
        <binding name="wsHttpBinding_IWcfPortal" maxReceivedMessageSize="2147483647">
          <readerQuotas maxBytesPerRead="2147483647" maxArrayLength="2147483647" maxStringContentLength="2147483647"
                        maxNameTableCharCount="2147483647" maxDepth="2147483647" />
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="returnFaults">
          <serviceDebug includeExceptionDetailInFaults="true" />

          <!-- Add the following element to your service behavior configuration. -->
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

 

EDIT:  I forgot to mention I can remote debug the WCF service and I see it is right at the point of throwing the DataPortalException that this happens.  I have an override of DataPortal_OnDataPortalException in my base class where I log the event and then call the base.DataPortal_OnDataPortalException(e, ex);

EDIT2:  OK this might help.  When I throw a custom exception on server side that inherits from SecurityException the connection is forcibly closed with no feedback.  So for testing I inherited from Exception and I now get this error on client.

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://ws.lhotka.net/WcfDataPortal:UpdateResult. The InnerException message was 'The constructor with parameters (SerializationInfo, StreamingContext) is not found in ISerializable type 'Company.BL.CaseAccessException'.'.  Please see InnerException for more details.

I noticed the CSLA exceptions have a constructor with those parameters.  Do I have to add a constructor with those parameters on every custom exception that I create?  Didn't realize there was a special way to code exceptions.  This is my exception class:

    [Serializable()]public class CaseAccessException : Exception
    {
        public CaseAccessException(string caseId)
            : base("Case #: '" + caseId + "' does not exist.")
        {
            //log the exception to the error log
            WriteErrorToTraceWithMessageAndCallerInfoAndTimestamp(this.Message);
        }
    }

JonnyBee replied on Sunday, March 22, 2015

Hi, 

I suspect there is something with the configuration of the client. 

Look at the SimpleNTier sample. It has w WinForms client and a Wcf server. 

I just added you small CaseAccessException to the DataAccess project and it is returned and deserialized just fine. 

 

swegele replied on Sunday, March 22, 2015

I stripped SimpleNTier to the bare bones and called it MuchSimplerNTier.  I attached the file. 

It demonstrates:

  1. Normal dataportal call over WCF
  2. Dataportal call with Exception NOT having serialization constructor
  3. Dataportal call with Exception HAVING serialization constructor
  4. Dataportal call with SecurityException closing connection

Hope this helps you see what I am talking about.  I fixed my code to never throw securityexceptions and to always have that special constructor.  But I would like others to know about it because I don't remember reading anything about this in the books or seen any posts about it.

Sean

JonnyBee replied on Monday, March 23, 2015

Hi, 

Yes, I can see the issue now. The solution is also detailed here: 

http://stackoverflow.com/questions/94488/what-is-the-correct-way-to-make-a-custom-net-exception-serializable

Copyright (c) Marimer LLC