Making the generated classes work with the XmlSerializer

Aug 12, 2009 at 9:04 PM

The project you download uses the DataContract serializer.  If you change the service contract to use the XmlSerializer you will find that the xml cannot be serialized into the TXLifeResponse class.  Here are the fixes to make it work. 

1.  On all XmlElement attributes within the generated Acord classes change the Form property to XmlSchemaForm.None.  See Example 1:

2.  You must define MessageContract classes so that the namespace of the service contract can be different from the namespace of your TXLifeRequest and TXLifeResponse classes See Example 2.

3.  The IsWrapped = false on the MessageContractAttribute can be set to true if you wish your TXLifeRequest and TXLifeResponse xml to be wrapped by the MessageContract class.

4.  Finally the XmlSerializer will not work with a large number of classes without increasing its maxNameTableCharCount and MTOM will not work without increasing some of the binding values.  See Example 3.

 5.  Using message contracts means you have to change your service agents so use svcutil.exe to generate your proxy and edit it as required.

After these few minor changes XmlSerialization works great.  Thanks for all the Help Microsoft and Acord.

Example 1.

[XmlElement(Type=typeof(InsTech.ForeSight.SalesPortal.Acord.DataContracts.ReserveMethod),ElementName="ReserveMethod",IsNullable=false,Form=XmlSchemaForm.None,Namespace=Declarations.SchemaVersion)]
Example 2.

[XmlSerializerFormat]
[ServiceContract(Name = "ClaimsNotification", Namespace = "http://InsuranceTechnologies.com/InsTech.ForeSight.SalesPortal.Acord.ServiceContracts/V1/")]
public interface IClaimsNotification
{
        /// <summary>
        /// This message provides the Receiver with a notification that the Requestor has been contacted regarding
        /// an event that has occurred relating to an insured entity, and may result in a Claim being filed under
        /// one or more Holdings. It does not create the Claim, but merely functions as the notification of the possibility
        /// of a Claim. Actions that result from the receipt of this notification are expected to vary by product and carrier.
        /// Transaction Code (tc) = 810
        /// </summary>
        /// <param name="request">TXLife Request Data</param>
        /// <returns>TXLife Response Data</returns>       
        [System.ServiceModel.OperationContractAttribute(Name = "SendFirstNoticeOfLoss",
            Action =      "http://InsuranceTechnologies.com/InsTech.ForeSight.SalesPortal.Acord.ServiceContracts/V1/ClaimsNotification/SendFirstNoticeOfLoss",
            ReplyAction = "http://InsuranceTechnologies.com/InsTech.ForeSight.SalesPortal.Acord.ServiceContracts/V1/ClaimsNotification/SendFirstNoticeOfLossResponse")]
        SendFirstNoticeOfLossResponse SendFirstNoticeOfLoss(SendFirstNoticeOfLossRequest request);
}
[System.ServiceModel.MessageContractAttribute(IsWrapped = false)]
public partial class SendFirstNoticeOfLossRequest
{
 [System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://ACORD.org/Standards/Life/2", Order = 1)]
 public InsTech.ForeSight.SalesPortal.Acord.DataContracts.TXLifeRequest TXLifeRequest;
  public SendFirstNoticeOfLossRequest() {}
  public SendFirstNoticeOfLossRequest(InsTech.ForeSight.SalesPortal.Acord.DataContracts.TXLifeRequest TXLifeRequest)
  {
     this.TXLifeRequest = TXLifeRequest;
  }
}

[System.ServiceModel.MessageContractAttribute(IsWrapped = false)]
public partial class SendFirstNoticeOfLossResponse
{
 [System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://ACORD.org/Standards/Life/2", Order = 1)]
 public InsTech.ForeSight.SalesPortal.Acord.DataContracts.TXLifeResponse TXLifeResponse;
 public SendFirstNoticeOfLossResponse() {}
 public SendFirstNoticeOfLossResponse(InsTech.ForeSight.SalesPortal.Acord.DataContracts.TXLifeResponse TXLifeResponse)
 {
  this.TXLifeResponse = TXLifeResponse;
 }
}

Example 3.

<binding name="NewBusinessServiceBinding" messageEncoding="Mtom" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
</binding>

<basicHttpBinding>
<binding name="NewBusinessService" closeTimeout="00:10:00" openTimeout="00:10:00"
receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
 <readerQuotas maxDepth="32" maxStringContentLength="65536" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="196608" />
</basicHttpBinding>

 

 

Sep 16, 2009 at 8:28 PM

Found the XmlSchemaForm problem too. This changeset, 26783, seems to address this by introducing the /q option that ignores elementFormDefault="unqualified" and attributeFormDefault="unqualified" declarations in all ACORD schemata. There seems to be a side-effect, /q removes the Namespace parameter of the generated XmlElement attribute in addition to XmlSchemaForm one.

May 11, 2010 at 5:40 PM

I found a bug in the XSDObjectGenLib.csproj for the /q option.  In order to get the Form=XmlSchemaForm.None to generate you need to comment out the If statements in the following locations.  See the code below:

Method ClassAttributeFieldCode in Static Class LanguageBase

        //if (attributeFormDefault == XmlSchemaForm.Qualified || attributeFormDefault == XmlSchemaForm.Unqualified)
        //{
			schemaForm = ",Form" + AttributeAssignmentOperator + "XmlSchemaForm." + attributeFormDefault.ToString();
			nameSpace = CalculateNamespace(schemaTargetNamespace, ns, dotNetDatatype == "System.Xml.XmlAttribute[]");
        //}

 

Method ClassElementFieldCode in Static Class LanguageBase

        //if (elementFormDefault == XmlSchemaForm.Qualified || elementFormDefault == XmlSchemaForm.Unqualified)
        //{
			schemaForm = ",Form" + AttributeAssignmentOperator + "XmlSchemaForm." + elementFormDefault.ToString();
			nameSpace = CalculateNamespace(schemaTargetNamespace, ns, dotNetDatatype == "System.Xml.XmlElement");
			
			// special case for  elements
			//  has XmlElement dotnet type.
			if (dotNetDatatype == "System.Xml.XmlElement" && nameSpace != "") 
				nameSpace = "Name" + AttributeAssignmentOperator + "\"" + fieldName2 + "\"" + nameSpace;
        //}Method ClassComplexTypeFieldCode in Static Class LanguageBase

 

        //if (elementFormDefault == XmlSchemaForm.Qualified || elementFormDefault == XmlSchemaForm.Unqualified)
        //{
			schemaForm = ",Form" + AttributeAssignmentOperator + "XmlSchemaForm." + elementFormDefault.ToString();
			nameSpace = CalculateNamespace(schemaTargetNamespace, ns, false);
        //}