.NET Core应用程序中的内容问题使用WCF服务

时间:2017-04-14 09:24:07

标签: wcf .net-core

我正在尝试使用新的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不是一个好的选择。

了解处理此问题的最佳方法是什么?

4 个答案:

答案 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>