Giter Club home page Giter Club logo

wcfcoremtomencoder's People

Contributors

lennykean avatar lokimidgard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

wcfcoremtomencoder's Issues

Client service missmatch

Hey there, thanks for the MtomEncoder

I'm getting

System.Private.CoreLib: Exception while executing function: GenerateId. System.Private.ServiceModel: Content Type application/soap+xml; charset=utf-8 was not supported by service --removed--. The client and service bindings may be mismatched.

here is my code

var encoding = new MtomMessageEncoderBindingElement(new System.ServiceModel.Channels.TextMessageEncodingBindingElement());

var transport = new System.ServiceModel.Channels.HttpsTransportBindingElement();
transport.AllowCookies = true;
transport.AuthenticationScheme = System.Net.AuthenticationSchemes.Basic;

var customBinding = new System.ServiceModel.Channels.CustomBinding(encoding, transport)
{
    Name = "BindingAuthBasicMtom",
    OpenTimeout = TimeSpan.FromMinutes(1),
    CloseTimeout = TimeSpan.FromMinutes(1),
    SendTimeout = TimeSpan.FromMinutes(10),
    ReceiveTimeout = TimeSpan.FromMinutes(10),
};

return customBinding;

The service requires ClientCredentialType = HttpClientCredentialType.Basic and uses BasicHttpBinding

Note: I changed HttpTransportBindingElement to HttpsTransportBindingElement

Any ideas?

Soap message version 1.1

When using the lib i got the following error "A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only endpoint"?
Are there any workarounds ?

Support .Net Standard

From the dependencys it seems it would alos work on .NetStandard. This would alows consuming this from .NetStandard libs.

Handle missing Content headers

While using your library, I noticed that several of my SOAP messages do not specify Content-Id or Content-Transfer-Encoding for the XML part of the multipart message. This caused an ArgumentNullException when attempting to match those headers against the Regex found in MtomMessageEncoder and MtomPart.

I attempted to fix this myself by changing the fallbacks in MtomPart from null to 8bit and String.Empty respectively. This resolved my issue. Are there any downsides to this solution? Would you like me to submit a PR?

Maybe unrelated, but the same messages also use domain names as part of their content IDs. For example:

<ImageData>
  <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:7bc0e65d-2fea-4e90-a6e6-bd77eee209c9%40www.mydomain.com"/>
</ImageData>

You'll notice that the @ symbol was URL-encoded to %40, but it was not URL-encoded in the Content-Id header. I was able to resolve this by URL-decoding the XML href attribute before comparing the two values. Again, are there any downsides to this solution?

Error with MTOM encoding .net core 2.2

I am consuming one of our third party vendor's soap and they are using MTOM encoding. My application is using .net core 2.2 and here is the code i am using but i am receiving excepiton.

var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement());
var transport = new HttpTransportBindingElement();
var customBinding = new CustomBinding(encoding, transport);

        EndpointAddress address =
                      new EndpointAddress("http://zzz.xxx.com:8976/dfdaf/2019.01/filemanagement?wsdl");
        FileManagement.FileManagementServiceClient client = new FileManagementServiceClient(customBinding, address);

But i am receiving following exception

The content type text/xml; charset=UTF-8 of the response message does not match the content type of the binding (application/soap+xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were:

ProtocolException: The content type text/xml; charset=UTF-8 of the response message does not match the content type of the binding (application/soap+xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were:

maxSizeOfHeaders limits the SOAP response content size

Hi, @lennykean! Is there a reason why the maxSizeOfHeaders is set to 1024 in the MtomMessageEncoder? And can it be a larger value? When receiving large amounts of data over SOAP (in the order of 50 MB), the XML buffer will exceeed its maximum size, and a system.ServiceModel.QuotaExceededException is thrown. The code I'm referring to is shown below.

public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType) { using (var stream = new MemoryStream(buffer.ToArray())) { var message = ReadMessage(stream, 1024, contentType); bufferManager.ReturnBuffer(buffer.Array); return message; } }

Make ReadAsMultipartAsync lazy

this looks like a great start. I've had a look at the code behind the ReadAsMultipartAsync method and it has one really big flaw. It reads the entire contents into memory. The typical usage I've seen with the MTOM encoder has been when needing to transfer large amounts of data over a SOAP service. Normally SOAP will encode a byte[] as base64 encoded string which increases it's size by ~30%. This is a lot when transferring 200MB of data. MTOM doesn't really gain you much unless you are sending large amounts of data. It might be possible to use the building blocks in the Microsoft.AspNet.WebApi.Client package to build something better. Basically an implementation of ReadAsMultipartAsync needs to lazily create each of the contained HttpContent objects. The HttpContent parts also need to return a stream from ReadAsStreamAsync which isn't backed by an in memory buffer but read from the actual network stream and fake an EOF once the part has been completely read.
What you've provided is great if you aren't returning a large amount of data, and the limitations are mainly in the Microsoft.AspNet.WebApi.Client code.
Edit:
I just asked a colleague on the ASP.NET Core team if there was a nicer implementation and he pointed me to this. You can see some sample usage here. It looks like it wouldn't take a lot of work to switch to using that implementation which solves these problems.

Wrong part is used as mainPart and therefore breaks on GetRawContent

Hi, thanks for making it possible to support MTOM for dotnet 5.

I am experiencing the following Exception:

System.ArgumentNullException: Value cannot be null. (Parameter 'input')
   at System.Text.RegularExpressions.ThrowHelper.ThrowArgumentNullException(ExceptionArgument arg)
   at System.Text.RegularExpressions.Regex.IsMatch(String input)
   at System.Text.RegularExpressions.Regex.IsMatch(String input, String pattern, RegexOptions options)
   at WcfCoreMtomEncoder.MtomPart.GetRawContent()
   at WcfCoreMtomEncoder.MtomPart.GetStringContentForEncoder(MessageEncoder encoder)
   at WcfCoreMtomEncoder.MtomMessageEncoder.ReadMessage(Stream stream, Int32 maxSizeOfHeaders, String contentType)
   at WcfCoreMtomEncoder.MtomMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType)
   at System.ServiceModel.Channels.MessageEncoder.ReadMessageAsync(Stream stream, BufferManager bufferManager, Int32 maxBufferSize, String contentType, CancellationToken cancellationToken)
   at System.ServiceModel.Channels.HttpResponseMessageHelper.ReadChunkedBufferedMessageAsync(Task`1 inputStreamTask, TimeoutHelper timeoutHelper)
   at System.ServiceModel.Channels.HttpResponseMessageHelper.ParseIncomingResponse(TimeoutHelper timeoutHelper)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.ReceiveReplyAsync(TimeoutHelper timeoutHelper)
   at System.ServiceModel.Channels.RequestChannel.RequestAsync(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.RequestAsyncInternal(Message message, TimeSpan timeout)
   at System.Runtime.TaskHelpers.WaitForCompletionNoSpin[TResult](Task`1 task)
   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.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args)

While debugging this package I observed the following:
MtomMessageEncoder.ReadMessage tries to get the mainPart by searching for the part with the parameter 'start'. If this parameter is not present, then it will take the first part.

With this mainPart, it will try to get the string content of that part. Before trying it will check if the Content-Transfer-Encoding is set to binary.

My issue is that the first part in the response I get from the WCF service is not a binary, but an XML. This part therefore has no Content-Transfer-Encoding.
image

Do you know how to mitigate this problem?

Sign the assembly

Any chance you could sign the assembly (strongname) and publish a new version of the nuget package?

.net Core is strict when parsing Content-Type headers

As @LokiMidgard found out (#1 (comment)), .net Core is much more sensitive to errors while parsing Content-Type headers. I had the same issue as him when parsing a Content-Type header ending in a semicolon - this is not allowed by the specifications but it's still out there.

Example response by an infringing web server:

HTTP/1.1 200 OK
Date: Fri, 29 Nov 2019 17:04:04 GMT
Server: Apache
Content-Length: 3420
Connection: close
Content-Type: multipart/related; type="application/xop+xml"; boundary="uuid:f7b7667f-56cf-4cda-b2b2-9c7a12450a3a"; start="<[email protected]>"; start-info="text/xml"

--uuid:f7b7667f-56cf-4cda-b2b2-9c7a12450a3a
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml";
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>...</soap:Body></soap:Envelope>
--uuid:f7b7667f-56cf-4cda-b2b2-9c7a12450a3a
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>

<?xml version="1.0"?>
...
--uuid:f7b7667f-56cf-4cda-b2b2-9c7a12450a3a--

The first part's Content-Type header ends with a ";" and triggers an exception.

"utf-8" Quotation Marks at encoding leads to error // Fix Found?

The old Mtom Soap Service we need to use in our .net core project returns as Content-Type this value:
Content-Type: application/xop+xml; type="application/soap+xml"; charset="utf-8"

Error Message:
Encoding is not supported ""utf-8""

The quotation marks lead to an error while trying to find the correct charset encoding. At one place in this library the quotation marks are replaced, but this seems not to be enough. I made a small change inside the class "MtomPart" at the Property ContentType, which did the job:

 public MediaTypeHeaderValue ContentType
        {
            get
            {
                string contentTypeHeaderValue = _part.Headers.GetValues("Content-Type").FirstOrDefault();

                if (!String.IsNullOrEmpty(contentTypeHeaderValue) && MediaTypeHeaderValue.TryParse(contentTypeHeaderValue.TrimEnd(';'), out var parsedValue))
                {
                    parsedValue.CharSet= parsedValue.CharSet.Replace("\"", "");
                    parsedValue.MediaType= parsedValue.MediaType.Replace("\"", "");
                    return parsedValue;
                }

                return _part.Headers.ContentType;
            }
        }

Could you release a new nuget package version with this fix?

Any way thanks for the great work with the mtom implementation :D

Regards
Manju

Sequence contains no elements Error

First off! THANK YOU for creating such a great package. It has definitely saved my bacon on this project.

I did find an issue that affected me when connecting to a WCF service using your Mtom encoder. I am making a service call that expects a document back and I received the "Sequence contains no elements Error" when making a call to 3rd party WCF service. I incorrectly thought that the service was bad but I was provided with a .NET 3.5 project that actually works.

To find the issue, I pulled down your repo and consumed it directly and found that the error is occurring in the following method:

`private static string ResolveRefs(string mainContent, IList parts)
{
bool ReferenceMatch(XAttribute hrefAttr, MtomPart part)
{
var partId = Regex.Match(part.ContentId, "<(?.)>");
var href = Regex.Match(hrefAttr.Value, "cid:(?.
)");

            return href.Groups["uri"].Value == partId.Groups["uri"].Value;
        }

        var doc = XDocument.Parse(mainContent);
        var references = doc.Descendants(XName.Get("Include", "http://www.w3.org/2004/08/xop/include")).ToList();

        foreach (var reference in references)
        {
            var referencedPart = (
                from part in parts
                where ReferenceMatch(reference.Attribute("href"), part)
                select part).Single();

            reference.ReplaceWith(Convert.ToBase64String(referencedPart.GetRawContent()));
        }
        return doc.ToString(SaveOptions.DisableFormatting);
    }`

Basically, this method was not finding any matches in the returned result from the WCF Service. When I debugged the code, I found that I should have been finding a match but there was a key difference. The RefenceMatch logic was not finding a match:

var partId = Regex.Match(part.ContentId, "<(?<uri>.*)>"); var href = Regex.Match(hrefAttr.Value, "cid:(?<uri>.*)");

In my case the second line of the above code was not URL decoded so the two URI didn't match. The web service was returning this uri encoded By adding WebUtility.UrlDecode to the hrefAttr.Value, it was able to find the match and give me my returned result.

Working code:
var href = Regex.Match(WebUtility.UrlDecode(hrefAttr.Value), "cid:(?<uri>.*)");

I'm not sure that this change should be added to the package but I wanted to post this here to help others if they run into this in the future.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.