title: Why does Visual Studio's web service serialization engine change when I make reference to an abstract class?
body: <p>I noticed this yesterday after some sleuthing, but wasn't happy with just knowing about it. Could someone explain this to me?</p>
  
  <p>Here's what I'm experiencing:</p>
  
  <ul>
  <li>I see two different serialization possibilities:
  <ul>
  <li><code>[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]</code></li>
  <li><code>[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]</code></li>
  </ul></li>
  <li>Serialization involving Runtime.Serialization causes the entity <code>ArrayOf&lt;T&gt;</code> to be introduced if any collections are expected as parameters to web methods.
  <ul>
  <li>public void Foo(int[] ids) ==> public void Foo(int[] ids) <strong>System.ServiceModel</strong></li>
  <li>public void Foo(int[] ids) ==> public void Foo(ArrayOfInt ids) <strong>System.Runtime.Serialization</strong></li>
  </ul></li>
  <li>The serialization engine chosen is dependent on a paramater deriving from (or being) an abstract class type.
  <ul>
  <li>public void Bar(int[] ids) ==> <strong>System.Runtime.Serialization</strong> is used.</li>
  <li>public void Bar(DerivedFromAbstractClass baz, int[] ids) ==> <strong>System.ServiceModel</strong> is used. </li>
  </ul></li>
  </ul>
  
  <p>As a runnable example:</p>
  
  <pre><code>public abstract class Foo { }
  
  /// &lt;summary&gt;
  /// Summary description for WebService1
  /// &lt;/summary&gt;
  [System.Web.Services.WebService(Namespace = "http://tempuri.org/")]
  [System.Web.Services.WebServiceBinding(ConformsTo = System.Web.Services.WsiProfiles.BasicProfile1_1)]
  [System.ComponentModel.ToolboxItem(false)]
  // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
  // [System.Web.Script.Services.ScriptService]
  public class WebService1 : System.Web.Services.WebService
  {
      [System.Web.Services.WebMethod]
      public void HelloWorld(Foo foo, int[] ids)
      {
      }
  }
  </code></pre>
  
  <p>Here is what my .asmx file looks like. Note the paramater types expected by hello world. Now, I generate a service reference:</p>
  
  <pre><code>namespace CableSolve.Web.Api.Tests.ServiceReference1 {
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.WebService1Soap")]
      public interface WebService1Soap {
  
          [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/HelloWorld", ReplyAction="*")]
          [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
          void HelloWorld(CableSolve.Web.Api.Tests.ServiceReference1.Foo foo, int[] ids);
      }
  
      /// &lt;remarks/&gt;
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.233")]
      [System.SerializableAttribute()]
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.ComponentModel.DesignerCategoryAttribute("code")]
      [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
      public abstract partial class Foo : object, System.ComponentModel.INotifyPropertyChanged {
  
          public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
  
          protected void RaisePropertyChanged(string propertyName) {
              System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
              if ((propertyChanged != null)) {
                  propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
              }
          }
      }
  
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      public interface WebService1SoapChannel : CableSolve.Web.Api.Tests.ServiceReference1.WebService1Soap, System.ServiceModel.IClientChannel {
      }
  
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      public partial class WebService1SoapClient : System.ServiceModel.ClientBase&lt;CableSolve.Web.Api.Tests.ServiceReference1.WebService1Soap&gt;, CableSolve.Web.Api.Tests.ServiceReference1.WebService1Soap {
  
          public WebService1SoapClient() {
          }
  
          public WebService1SoapClient(string endpointConfigurationName) : 
                  base(endpointConfigurationName) {
          }
  
          public WebService1SoapClient(string endpointConfigurationName, string remoteAddress) : 
                  base(endpointConfigurationName, remoteAddress) {
          }
  
          public WebService1SoapClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                  base(endpointConfigurationName, remoteAddress) {
          }
  
          public WebService1SoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                  base(binding, remoteAddress) {
          }
  
          public void HelloWorld(CableSolve.Web.Api.Tests.ServiceReference1.Foo foo, int[] ids) {
              base.Channel.HelloWorld(foo, ids);
          }
      }
  }
  </code></pre>
  
  <p>Note the absence of ArrayOfInt. Now, I remove the Foo paramater from WebService1 and generate a second service reference. Observe:</p>
  
  <pre><code>namespace CableSolve.Web.Api.Tests.ServiceReference2 {
      using System.Runtime.Serialization;
      using System;
  
  
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
      [System.Runtime.Serialization.CollectionDataContractAttribute(Name="ArrayOfInt", Namespace="http://tempuri.org/", ItemName="int")]
      [System.SerializableAttribute()]
      public class ArrayOfInt : System.Collections.Generic.List&lt;int&gt; {
      }
  
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference2.WebService1Soap")]
      public interface WebService1Soap {
  
          // CODEGEN: Generating message contract since element name ids from namespace http://tempuri.org/ is not marked nillable
          [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/HelloWorld", ReplyAction="*")]
          CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponse HelloWorld(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest request);
      }
  
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
      [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
      public partial class HelloWorldRequest {
  
          [System.ServiceModel.MessageBodyMemberAttribute(Name="HelloWorld", Namespace="http://tempuri.org/", Order=0)]
          public CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequestBody Body;
  
          public HelloWorldRequest() {
          }
  
          public HelloWorldRequest(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequestBody Body) {
              this.Body = Body;
          }
      }
  
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
      [System.Runtime.Serialization.DataContractAttribute(Namespace="http://tempuri.org/")]
      public partial class HelloWorldRequestBody {
  
          [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
          public CableSolve.Web.Api.Tests.ServiceReference2.ArrayOfInt ids;
  
          public HelloWorldRequestBody() {
          }
  
          public HelloWorldRequestBody(CableSolve.Web.Api.Tests.ServiceReference2.ArrayOfInt ids) {
              this.ids = ids;
          }
      }
  
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
      [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
      public partial class HelloWorldResponse {
  
          [System.ServiceModel.MessageBodyMemberAttribute(Name="HelloWorldResponse", Namespace="http://tempuri.org/", Order=0)]
          public CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponseBody Body;
  
          public HelloWorldResponse() {
          }
  
          public HelloWorldResponse(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponseBody Body) {
              this.Body = Body;
          }
      }
  
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
      [System.Runtime.Serialization.DataContractAttribute()]
      public partial class HelloWorldResponseBody {
  
          public HelloWorldResponseBody() {
          }
      }
  
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      public interface WebService1SoapChannel : CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap, System.ServiceModel.IClientChannel {
      }
  
      [System.Diagnostics.DebuggerStepThroughAttribute()]
      [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
      public partial class WebService1SoapClient : System.ServiceModel.ClientBase&lt;CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap&gt;, CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap {
  
          public WebService1SoapClient() {
          }
  
          public WebService1SoapClient(string endpointConfigurationName) : 
                  base(endpointConfigurationName) {
          }
  
          public WebService1SoapClient(string endpointConfigurationName, string remoteAddress) : 
                  base(endpointConfigurationName, remoteAddress) {
          }
  
          public WebService1SoapClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                  base(endpointConfigurationName, remoteAddress) {
          }
  
          public WebService1SoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                  base(binding, remoteAddress) {
          }
  
          [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
          CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponse CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap.HelloWorld(CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest request) {
              return base.Channel.HelloWorld(request);
          }
  
          public void HelloWorld(CableSolve.Web.Api.Tests.ServiceReference2.ArrayOfInt ids) {
              CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest inValue = new CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequest();
              inValue.Body = new CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldRequestBody();
              inValue.Body.ids = ids;
              CableSolve.Web.Api.Tests.ServiceReference2.HelloWorldResponse retVal = ((CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap)(this)).HelloWorld(inValue);
          }
      }
  }
  </code></pre>
  
  <p>What the heck? <strong>Why does HelloWorld's second paramater's type expectations depend on the existence of another paramater deriving from or being an abstract class? Is it possible to have HelloWorld only expect int[] ids without the Foo paramater, but not have it expect ArrayOfInt?</strong></p>