Why does the Visual Studio Web Service serialization mechanism change when I refer to an abstract class?

I noticed this yesterday after some surveillance, but was not happy just knowing it. Can anyone explain this to me?

Here is what I am experiencing:

  • I see two different serialization options:
    • [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    • [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
  • Serialization using Runtime.Serialization causes the ArrayOf<T> entity to be entered if any collections are expected as parameters for web methods.
    • public void Foo (int [] ids) ==> public void Foo (int [] ids) System.ServiceModel
    • public void Foo (int [] ids) ==> public void Foo (ArrayOfInt ids) System.Runtime.Serialization
  • The serialization mechanism is selected, depending on the parameter that receives (or is) an abstract type of the class.
    • public void Bar (int [] ids) ==> used by System.Runtime.Serialization .
    • public void Bar (DerivedFromAbstractClass baz, int [] ids) ==> Used by System.ServiceModel .

As an example run:

 public abstract class Foo { } /// <summary> /// Summary description for WebService1 /// </summary> [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) { } } 

This is what my .asmx file looks like. Pay attention to the paramater types expected in the hello world. Now I am creating a service link:

 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); } /// <remarks/> [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<CableSolve.Web.Api.Tests.ServiceReference1.WebService1Soap>, 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); } } } 

Note the lack of ArrayOfInt. Now I remove Foo paramater from WebService1 and generate a second service link. Note:

 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<int> { } [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<CableSolve.Web.Api.Tests.ServiceReference2.WebService1Soap>, 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); } } } 

What the hell? Why are the HelloWorld expectations of the second type with parameters dependent on the existence of another parameter, a derived or abstract class? Is it possible that HelloWorld would expect int [] ids without a Foo paramater, but would it expect ArrayOfInt?

+4
source share

Source: https://habr.com/ru/post/1435091/


All Articles