Matt Burland
Matt Burland

Reputation: 45155

Setting up a streaming WCF service in sharepoint

I'm trying to set up a simple WCF service in sharepoint that will take a stream and return a steam. It has a method that looks like this:

public System.IO.Stream Convert(System.IO.Stream input)
{
   // do stuff here
}

At first, I could get it working because it complained about the size of the request. I figured out that this was due to not setting it up for steaming on the server side. So in the web.config, I set up its binding like this:

<binding name="testBinding" maxBufferPoolSize="214748347" maxBufferSize="214748347" 
             maxReceivedMessageSize="214748347"
             transferMode="Streamed">

And that seemed to solve the first problem, I could now see a steam in my Convert method and it seems to be processing it. The problem now is on the return leg. In my client side code I did something like this:

        using (StreamReader sr = new StreamReader(file))
        {
            var sout = ts.Convert(sr.BaseStream);
            using (var fs = File.Create(file + ".converted"))
            {
                while ((read = sout.Read(buffer, 0, buffer.Length)) > 0)
                {
                    fs.Write(buffer, 0, read);
                    Console.WriteLine("Wrote " + read + " bytes...");
                }
            }
        }

But the problem was that read was always 0. There never seemed to be bytes to read even though I could confirm that the steam has data on the server side. So it occurred to me that the problem is that I need to get the transferMode on the client side too. So I set it like this:

        <basicHttpBinding>
            <binding name="BasicHttpBinding_iSPTest" transferMode="Streamed">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Ntlm" />
                  <message clientCredentialType="UserName" algorithmSuite="Default"/>
                </security>
            </binding>
        </basicHttpBinding>

But now when I try and hit any method on my service (including regular, non-steam one), I get this error:

HTTP request streaming cannot be used in conjunction with HTTP authentication.  
Either disable request streaming or specify anonymous HTTP authentication.

Which seems straightforward enough, except I can't figure out how to get the Sharepoint server to accept anonymous connections. If I remove the security stuff, or add a security section on the server side with mode = none, I get MessageSecurityException:

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. 
The authentication header received from the server was 'NTLM'.

So what's going on here? How do I get my returned stream to be readable? Do I need to set the server to allow anonymous access? If so, how?

Upvotes: 2

Views: 391

Answers (1)

x0n
x0n

Reputation: 52480

I answer your question indirectly as an aside to a slightly different question:

Catch-22 prevents streamed TCP WCF service securable by WIF; ruining my Christmas, mental health

My answer does not deal with sharepoint specifically, but it is applicable in your case. Essentially the gist is that the whole challenge/response 401 exchange is not compatible with streaming because the stream may be sent twice (and denied with a 401 on the first attempt). The trick is to send the authentication with the first request. This is done with a custom client behavior/inspector combo and disabling authentication in the client WCF config, but leaving it enabled on the server. Disabling authentication for a single WCF service on the server side will cause more headaches than it's worth in a sharepoint context. Trust me :)

Good luck.

Upvotes: 1

Related Questions