我正在尝试使用新的Visual Studio WCF连接服务从.NET Core Web API调用WCF服务方法。
但是当我测试这个时,我收到以下错误: -
内容类型multipart / related;类型= “应用/ XOP + xml” 的;开始= “http://tempuri.org/0”;边界= “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 内容传输编码:8位 Content-Type:application / xop + xml; charset = utf-8; type =“text / xml”
公开的WCF服务使用MTOM MessageEncoding,在传统的.NET框架客户端应用程序中,我们可以将客户端设置为在应用程序的配置文件中使用MTOM,但在.NET核心中,我们没有可以设置的配置文件MessageEncoding和所有这些配置 在Reference.cs中存在的代码(生成的文件)中处理。 我想改变这个生成的文件来设置MessageEncoding不是一个好的选择。
了解处理此问题的最佳方法是什么?
答案 0 :(得分:4)
我刚从WCF核心团队了解到,基于.NET Core的客户端目前不支持MTOM编码。这是一个要求的功能,将在以后的版本中提供。 这是github链接,其中包含更多信息:Adding MTOM support in WCF runtime
答案 1 :(得分:3)
我在项目中面临同样的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;
注意:myParameter&amp; myResponse是第1步生成的类
可能有更简单的方法,但至少,这是有效的。 希望你们中的一些人觉得这很有帮助。
答案 2 :(得分:0)
就我而言,我通过在我的 .NET Core 2.1 项目中使用 WcfCoreMtomEncoder 包解决了这个问题。您可以详细了解如何使用它here
答案 3 :(得分:-2)
我通过安装最新版本的visual studio 2017解决了这个问题。通过安装最新版本的visual studio,它会自动将你的网络核心更新到最新版本(1.1.2)。
你也可以使用“binaryMessageEncodingBindingElement”:
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.CreatedInvoice)
</th>
<th>
@Html.DisplayNameFor(model => model.InvoicePath)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.CreatedInvoice)
</td>
<td>
@Html.DisplayFor(modelItem => item.InvoicePath)
</td>
<td>
@Html.ActionLink("Download", "GetPdf", new { id = item.InvoicePath })
</td>
</tr>
}
</table>