-
Notifications
You must be signed in to change notification settings - Fork 571
Description
Describe the bug
When an ASMX web service has an optional parameter (one marked with System.ComponentModel.DefaultValueAttribute), dotnet-svcutil with "serializer": "XmlSerializer" generates for that service code that fails upon trying to call that method, with the following stack trace:
System.ServiceModel.CommunicationException: There was an error in serializing body of message FrobberPlopRequest: 'There was an error generating the XML document.'. Please see InnerException for more details.
---> System.InvalidOperationException: There was an error generating the XML document.
---> System.InvalidProgramException: Invalid IL code in Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterMyApplicationSoap:Write40_FrobberPlop (object[]): IL_01bb: ceq
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer14.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle)
at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, XmlSerializer serializer, MessagePartDescription returnPart, MessagePartDescriptionCollection bodyParts, Object returnValue, Object[] parameters) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs:line 390
at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs:line 330
--- End of inner exception stack trace ---
at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Dispatcher/XmlSerializerOperationFormatter.cs:line 363
at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Dispatcher/OperationFormatter.cs:line 370
at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Dispatcher/OperationFormatter.cs:line 773
at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer) in #/_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/BodyWriter.cs:line 132
at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/Message.cs:line 1191
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/Message.cs:line 779
at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/Message.cs:line 711
at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/BufferedMessageWriter.cs:line 60
at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessageAsync(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/TextMessageEncoder.cs:line 527
at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/TextMessageEncoder.cs:line 475
at System.ServiceModel.Channels.MessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/MessageEncoder.cs:line 120
at System.ServiceModel.Channels.BufferedMessageContent.EnsureMessageEncoded() in /_/src/System.ServiceModel.Http/src/System/ServiceModel/Channels/MessageContent.cs:line 247
at System.ServiceModel.Channels.BufferedMessageContent.TryComputeLength(Int64& length) in /_/src/System.ServiceModel.Http/src/System/ServiceModel/Channels/MessageContent.cs:line 268
at System.Net.Http.HttpContent.GetComputedOrBufferLength()
at System.Net.Http.Headers.HttpContentHeaders.get_ContentLength()
at Xamarin.Android.Net.AndroidMessageHandler.SetupRequestBody(HttpURLConnection httpConnection, HttpRequestMessage request) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs:line 1340
at Xamarin.Android.Net.AndroidMessageHandler.SetupRequestInternal(HttpRequestMessage request, URLConnection conn) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs:line 1134
at Xamarin.Android.Net.AndroidMessageHandler.DoSendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Xamarin.Android.Net/AndroidMessageHandler.cs:line 496
at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at ##System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.<SendRequestAsync>d__13[[System.ServiceModel.Channels.IRequestChannel, System.ServiceModel.Primitives, Version=8.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]].MoveNext() in /_/src/System.ServiceModel.Http/src/System/ServiceModel/Channels/HttpChannelFactory.cs:line 1056
at System.ServiceModel.Channels.RequestChannel.RequestAsync(Message message, TimeSpan timeout) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/RequestChannel.cs:line 267
at System.ServiceModel.Channels.RequestChannel.RequestAsyncInternal(Message message, TimeSpan timeout) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/RequestChannel.cs:line 238
at System.Runtime.TaskHelpers.WaitForCompletionNoSpin[Message](Task`1 task) in /_/src/System.ServiceModel.Primitives/src/Internals/System/Runtime/TaskHelpers.cs:line 294
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/RequestChannel.cs:line 227
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Dispatcher/RequestChannelBinder.cs:line 107
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannel.cs:line 760
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannel.cs:line 717
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs:line 390
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args) in /_/src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs:line 144
at generatedProxy_1.FrobberPlop(FrobberPlopRequest )
at MyApplication.FrobberService.FrobberSoapClient.MyApplication.FrobberService.FrobberServiceSoap.FrobberPlop(FrobberPlopRequest request) in C:\Users\...\Reference.cs:line 2586
at MyApplication.FrobberService.FrobberSoapClient.FrobberPlop(String Batch, Nullable`1 Zone, String Template, Byte NumberOfPlops, Int32 PersonID, String FrobberName, Boolean AllowCreate, Boolean AllowContinue) in C:\Users\...\Reference.cs:line 2600
at MyApplication.MainActivity.StartFrobberPlop(String frobber_name, Byte number_of_plops) in C:\Users\...\MainActivity.cs:line 1391} System.ServiceModel.CommunicationException
To Reproduce
Have an ASMX web service that exposes a similar method:
public DoesntMatterWhat FrobberPlop(
string Batch,
char? Zone,
string Template,
byte NumberOfPlops,
int PersonID,
string FrobberName,
[System.ComponentModel.DefaultValue(true)] bool AllowCreate,
[System.ComponentModel.DefaultValue(true)] bool AllowContinue
)Generate a wrapper for it using dotnet-svcutil and the following ConnectedService.json:
{
"ExtendedData": {
"inputs": [
"https://very.intranet.address.com/Services/FrobberService/FrobberService.asmx"
],
"collectionTypes": [
"System.Array",
"System.Collections.Generic.Dictionary`2"
],
"namespaceMappings": [
"*, MyApplication.FrobberService"
],
"sync": true,
"targetFramework": "net9.0-android",
"typeReuseMode": "All",
"serializer": "XmlSerializer"
}
}Observe that that following classes and methods have been generated in Reference.cs:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName="FrobberPlop", WrapperNamespace="http://very.intranet.address.com/ns/xml-services/frobber", IsWrapped=true)]
public partial class FrobberPlopRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=0)]
public string Batch;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=1)]
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public System.Nullable<char> Zone;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=2)]
public string Template;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=3)]
public byte NumberOfPlops;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=4)]
public int PersonID;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=5)]
public string FrobberName;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=6)]
[System.ComponentModel.DefaultValueAttribute(true)]
public bool AllowCreate;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=7)]
[System.ComponentModel.DefaultValueAttribute(true)]
public bool AllowContinue;
public FrobberPlopRequest()
{
}
public FrobberPlopRequest(string Batch, System.Nullable<char> Zone, string Template, byte NumberOfPlops, int PersonID, string FrobberName, bool AllowCreate, bool AllowContinue)
{
this.Batch = Batch;
this.Zone = Zone;
this.Template = Template;
this.NumberOfPlops = NumberOfPlops;
this.PersonID = PersonID;
this.FrobberName = FrobberName;
this.AllowCreate = AllowCreate;
this.AllowContinue = AllowContinue;
}
}[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", ConfigurationName="MyApplication.FrobberService.FrobberServiceSoap")]
public interface FrobberServiceSoap
{
// CODEGEN: Parameter 'Zone' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'Microsoft.Xml.Serialization.XmlElementAttribute'.
[System.ServiceModel.OperationContractAttribute(Action="http://very.intranet.address.com/ns/xml-services/frobber/FrobberPlop", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(SomeNestedResult))]
MyApplication.FrobberService.FrobberPlopResponse FrobberPlop(MyApplication.FrobberService.FrobberPlopRequest request);
}[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
public partial class FrobberSoapClient : System.ServiceModel.ClientBase<MyApplication.FrobberService.FrobberServiceSoap>, MyApplication.FrobberService.FrobberServiceSoap
{
public MyApplication.FrobberService.DoesntMatterWhat FrobberPlop(string Batch, System.Nullable<char> Zone, string Template, byte NumberOfPlops, int PersonID, string FrobberName, bool AllowCreate, bool AllowContinue)
{
MyApplication.FrobberService.FrobberPlopRequest inValue = new MyApplication.FrobberService.FrobberPlopRequest();
inValue.Batch = Batch;
inValue.Zone = Zone;
inValue.Template = Template;
inValue.NumberOfPlops = NumberOfPlops;
inValue.PersonID = PersonID;
inValue.FrobberName = FrobberName;
inValue.AllowCreate = AllowCreate;
inValue.AllowContinue = AllowContinue;
MyApplication.FrobberService.FrobberPlopResponse retVal = ((MyApplication.FrobberService.FrobberServiceSoap)(this)).FrobberPlop(inValue);
return retVal.DoesntMatterWhat;
}
}Attempt to consume the service from the client code:
using (var c = new FrobberService.FrobberServiceSoapClient(FrobberServiceSoapClient.EndpointConfiguration.FrobberServiceSoap12))
{
var result = c.FrobberFlop(batch, zone, template, plops, person_id, "Frobber12", true, true);
}Observe the exception quoted above with
System.InvalidProgramException: Invalid IL code in Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterMyApplicationSoap:Write40_FrobberPlop (object[]): IL_01bb: ceq
Workaround
You can comment out the DefaultValueAttribute from the generated class, in which case everything will start working:
public partial class FrobberPlopRequest
{
...
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=6)]
//[System.ComponentModel.DefaultValueAttribute(true)] // Commented out - crashes at runtime
public bool AllowCreate;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://very.intranet.address.com/ns/xml-services/frobber", Order=7)]
//[System.ComponentModel.DefaultValueAttribute(true)] // Commented out - crashes at runtime
public bool AllowContinue;
}Expected behaviour
The generated code does not crash at runtime, whether or not it has to process the DefaultValueAttribute.
Additional context
I am seeing this in an Android application that uses the new .NET Android template and depends on an ASMX webservice. I don't know if it manifests in other types of projects.