我正在尝试使用新的Visual Studio WCF Connected服务从.NET Core Web API调用WCF服务方法。
但是,当我对此进行测试时,出现以下错误:
内容类型为多部分/相关;type =“ application / xop + xml”; start =“ http://tempuri.org/0 ”; boundary =“ uuid:9e7f9b02-4d9c-4ec1-bad4-1007704a579a + id = 1197”; 响应消息的start-info =“ text / xml”与绑定的内容类型不匹配(text / xml; charset = utf-8)。如果使用自定义编码器,请确保正确实施IsContentTypeSupported方法。响应的前1024个字节为:'--uuid:9e7f9b02-4d9c-4ec1-bad4-1007704a579a + id = 1197 Content-ID:http ://tempuri.org/0 Content-Transfer-Encoding:8位内容类型:application / xop + xml; charset = utf-8; type =“ text / xml”
公开的WCF服务使用MTOM MessageEncoding,在传统的.NET Framework客户端应用程序中,我们可以在应用程序的配置文件中将客户端设置为使用MTOM,但在.NET Core中,我们没有可在其中设置MessageEncoding和所有这些配置都在Reference.cs(这是一个生成的文件)中提供的代码中进行了处理。我认为更改此生成的文件以设置MessageEncoding不是一个好选择。
对解决此问题的最佳方法有什么想法?
我在我的项目中遇到了同样的 MTOM 消耗问题,并且必须找到一种能够使用该服务的方法。它以一些(丑陋的)代码结束,但功能强大。
我只是想分享解决方案(因为我在网上找不到任何东西):
首先,通过添加连接的服务(就像您对常规 SOAP 客户端所做的那样)使用 Visual Studio(在我的情况下为 2017)生成客户端。这将帮助您节省大量的虚拟代码输入;)
然后,使用 RestSharp 调用端点,并手动序列化响应/请求:
var client = new RestClient("http://myService/Service");
var request = new RestRequest(Method.POST);
request.AddHeader("accept", "text/plain");
request.AddHeader("content-type", "text/xml");
// create parameter
var serializer = new XmlSerializer(typeof(myParameter));
var requestParameter = new myParameter(1,2,3,4);
string requestParameterStr;
var namepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true, NamespaceHandling = NamespaceHandling.OmitDuplicates }; // some parameters to make it clean, only OmitXmlDeclaration is mandatory
using (var stringWriter = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, requestParameter, namepsaces);
requestParameterStr = stringWriter.ToString();
}
}
// patch parameter to add the namespace prefix required by consumer service
requestParameterStr = requestParameterStr.Replace("myParameter", "myNs:myParameter");
// wrap parameter in a soap envelop
requestParameterStr =
$"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:myNs=\"http://myService/Service/\"><soapenv:Header/><soapenv:Body>{requestParameterStr}</soapenv:Body></soapenv:Envelope>";
request.AddParameter(
"text/xml",
requestParameterStr,
ParameterType.RequestBody);
var response = client.Execute(request);
var mtomMsg = response.Content;
// remove MTOM elements from the received Content. here comes the ugly part ^^
var responseContentType = response.ContentType;
var contentTypeElements = responseContentType.Split(";");
var boundary = contentTypeElements.FirstOrDefault(x => x.TrimStart().StartsWith("boundary="))?.Trim().Substring("boundary=".Length);
var startElement = contentTypeElements.FirstOrDefault(x => x.TrimStart().StartsWith("start="))?.Trim().Substring("start=".Length);
boundary = boundary.Trim('"');
startElement = startElement.Trim('"');
var startIndex = mtomMsg.IndexOf(startElement) + startElement.Length;
var endIndex = mtomMsg.LastIndexOf("--" + boundary + "--", startIndex);
var cleanedMtomMsg = mtomMsg.Substring(startIndex, endIndex - startIndex);
// Get the result inside the Soap envelop
var soapDocument = XDocument.Parse(cleanedMtomMsg);
var envelopeElt = soapDocument.Root;
var bodyElt = (System.Xml.Linq.XElement)envelopeElt.FirstNode;
var responseStr = bodyElt.FirstNode.ToString();
// deserialize the result
var memstream = new MemoryStream(Encoding.UTF8.GetBytes(responseStr));
var reader = XmlDictionaryReader.CreateTextReader(memstream, XmlDictionaryReaderQuotas.Max);
var deserializer = new XmlSerializer(typeof(myResponse), "http://myService/Service/"); // don't forget the namespace
var result = deserializer.Deserialize(reader) as myResponse;
Run Code Online (Sandbox Code Playgroud)注意:myParameter 和 myResponse 是在步骤 1 中生成的类
可能有更简单的方法,但至少,这是有效的。希望你们中的一些人觉得这有帮助。
我只是从WCF Core团队了解到,当前基于.NET Core的客户端不支持MTOM编码。这是一项要求的功能,它将在以后的版本中提供。这是具有更多信息的github链接:在WCF运行时中添加MTOM支持
| 归档时间: |
|
| 查看次数: |
3429 次 |
| 最近记录: |