我正在尝试将 WSDL 用于我无法控制/修改的服务。使用 VS2022,我通过“添加连接服务”将连接服务添加到 WSDL。
我希望有人能够对此进行审查并为我提供比我从供应商那里得到的更好的答案。供应商表示“无法提供编码帮助”,我理解原因。
这里的问题是由以前版本的更改引起的,现在需要值数组而不是单个值。
数组的类型定义为object[] Items;它应该是字符串数组或 Guid 数组。 Guid 数组是每个供应商的首选。这就是Guid数组的问题。
我收到编译器错误“无法将类型 'System.Guid[]' 隐式转换为 'object[]'”或“无法将类型 'System,Guid[]' 转换为 object[]'”,具体取决于使用的强制转换或不。
分配正确的类型(object[])后,我收到运行时错误“失败(CancelIndiciumRequest):调用错误:mscorlib:序列化消息 CancelIndiciumRequest 正文时出错:‘生成 XML 文档时出错。’。请参阅有关更多详细信息,请参阅 InnerException。 ==> System.Xml: System.InvalidOperationException: 生成 XML 文档时出错。 ---> System.InvalidOperationException:在此上下文中不能使用 System.Guid 类型。”
主要调用的方法是:
internal int CancelLabel(string trackNum)
{
CancelIndiciumRequest req = new CancelIndiciumRequest
{
Item = GetCredsType(),
//Isue assignment begins:
//Items = (object[]) new Guid[] { new Guid(trackNum) }, <= Syntax error(s)
//These get runtime error
//Items = (new List<Guid> { new Guid(trackNum) }).ToArray(),
//Items = GetArrayGuid(trackNum),
//Items = GetGuids(trackNum).ToArray();
//End issue
};
...removed excess code
resp = GetResponse(req);
}
支持方式:
private List<Guid> GetGuids(string TxID)
{
return new List<Guid> { new Guid(TxID) };
}
private object[] GetArrayGuid(string sGuid)
{
object[] oAry = new object[1];
oAry[0] = new Guid(sGuid);
return oAry;
}
我的呼叫代码是:
private CancelIndiciumResponse GetResponse(CancelIndiciumRequest req)
{
XSoap x = sFactory.CreateChannel();
CancelIndiciumResponse resp = null;
int retry = 0;
while (resp == null && retry < 1)
{
try
{
resp = x.CancelIndicium(req); ,=== this is the call into Connected service genned code
_authToken = resp.Authenticator;
}
catch (FaultException ex)
{
...Error handling here
} // catch (FaultException ex)
catch (Exception ex)
{
...Error handling here
}
retry++;
} //while (resp == null && retry < 2)
return resp;
}
连接的服务代码是(删除了对实际 URL 和命名空间的引用):
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName="CancelIndicium", WrapperNamespace="http://x.com/xml/namespace/2023/07/x/x", IsWrapped=true)]
public partial class CancelIndiciumRequest {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://x.com/xml/namespace/2023/07/x/x", Order=0)]
[System.Xml.Serialization.XmlElementAttribute("Authenticator", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Credentials", typeof(Credentials))]
public object Item;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://x.com/xml/namespace/2023/07/x/x", Order=1)]
[System.Xml.Serialization.XmlElementAttribute("xTxIDs", typeof(System.Guid[]))]
[System.Xml.Serialization.XmlElementAttribute("xNumbers", typeof(string[]))]
public object[] Items;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://x.com/xml/namespace/2023/07/x/x", Order=2)]
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public System.Nullable<bool> SendEmail;
public CancelIndiciumRequest() {
}
public CancelIndiciumRequest(object Item, object[] Items, System.Nullable<bool> SendEmail) {
this.Item = Item;
this.Items = Items;
this.SendEmail = SendEmail;
}
}
我没有找到解决办法。当我深入挖掘时,这是使用 exception.tostring(); 的完整异常
System.ServiceModel.CommunicationException: There was an error in serializing body of message CancelIndiciumRequest: '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.InvalidOperationException: The type System.Guid may not be used in this context.
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSwsimV135Soap.Write269_CancelIndicium(Object[] p)
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer72.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.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, XmlSerializer serializer, MessagePartDescription returnPart, MessagePartDescriptionCollection bodyParts, Object returnValue, Object[] parameters)
at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer)
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at USPostal.SWSIM.SwsimV135Soap.CancelIndicium(CancelIndiciumRequest request)
at USPostal.StampsApiInterface.GetResponse(CancelIndiciumRequest req) in C:\Users\lawre\Source\Repos\USPostalAPI\USPostal\InterfaceClasses\StampsApiInterface.cs:line 1954
由于连接服务的代码是由代码生成引擎生成的,因此我考虑了如何扩展代码并使其工作。我是这个领域的真正新手。
来自 Reference.cs 的顶部:
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
这就是我所做的:我将类中的方法放入另一个文件中。它已经是一个部分类,我想要更改的参数应该是有效的更改。但编译器属性阻止了它按我希望的方式工作。
我将所需的类放入相同的名称空间但不同的文件中。 请参阅上面的代码以了解已识别的类。我根据需要更改了代码,基本上用 Guid[] 替换了 object[]。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "CancelIndicium", WrapperNamespace = "http://x.com/xml/namespace/2023/07/x/xV135", IsWrapped = true)]
public partial class CancelIndiciumRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://x.com/xml/namespace/2023/07/x/xV135", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("Authenticator", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Credentials", typeof(Credentials))]
public object Item;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://x.com/xml/namespace/2023/07/x/xV135", Order = 1)]
[System.Xml.Serialization.XmlElementAttribute("xTxIDs", typeof(System.Guid[]))]
public Guid[] Items;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://x.com/xml/namespace/2023/07/x/xV135", Order = 2)]
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true)]
public System.Nullable<bool> SendEmail;
public CancelIndiciumRequest()
{
}
public CancelIndiciumRequest(object Item, Guid[] Items, System.Nullable<bool> SendEmail)
{
this.Item = Item;
this.Items = Items;
this.SendEmail = SendEmail;
}
}
我必须注释掉 codegen Reference.cs 中的代码。我运行了 UI 测试并每次都得到了预期的响应。我知道必须有一种更简洁的方法,并且如果我从 WSDL 重新生成代码,我将手动编辑。