2

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?

Paul Rowland
  • 8,244
  • 12
  • 55
  • 76
Matt Burland
  • 44,552
  • 18
  • 99
  • 171

1 Answers1

1

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.

Community
  • 1
  • 1
x0n
  • 51,312
  • 7
  • 89
  • 111
  • Thanks for the link. This one will take me a while to digest. At the moment, we are only actually using Sharepoint for a single purpose. It's not something we are using generally (hence our unfamiliarity with it). Of course, that may change if we decide we want to use it for something else some time later, so I'd prefer not to leave future headaches. – Matt Burland Oct 16 '14 at 01:23
  • Ok: I implemented what you had in the linked answer changing nothing on the server-side and setting the client side to use the custom behavior, but now I get an argument exception with the message `The provided URI scheme 'http' is invalid; expected 'https'.` – Matt Burland Oct 16 '14 at 14:11
  • I changed the `endpoint` address (on the client-side) to `https://myserver...` from `http`, but then I get a "no endpoint listening at https://....". I changed the `security` mode on the server from `none` to `transport`, but still no dice. – Matt Burland Oct 16 '14 at 14:21
  • So you don't have SSL enabled on the server? Ok, so don't use transport security. It should be "none" and the url protocol should be "http" – x0n Oct 16 '14 at 14:40
  • With `security mode="None"` on both the server and the client, I'm back to were I started with the `The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'NTLM'.` – Matt Burland Oct 16 '14 at 14:50
  • I fiddled around some more and set up an https binding for sharepoint and now I don't have the "no endpoint listening" problem, but I'm back to it complaining about 'NTLM'! – Matt Burland Oct 16 '14 at 15:25
  • ok, security mode should be none in the configuration, but the point of the client inspector code is inject authentication directly onto the wire. Are you sure you've wired it all up correctly? You may need to just sit back and read about how my code works. – x0n Oct 16 '14 at 15:41
  • Hmm, actually, there's another major point of dissonance here - my code is performing BASIC auth, you've got sharepoint set up only for NTLM. Try enabling BASIC auth as well as NTLM (windows integrated) for the site. – x0n Oct 16 '14 at 15:44
  • I actually did notice that a little while ago. I figured out where to set edit authentication in sharepoint and clicked the checkbox for "basic" authentication, but it still insisted it wanted NTLM even after restarting the server. Just for laughs, I went ahead and tried turning on annoymous access and setting security to none and that did work (although probably isn't desirable), but I'm now I'm really back to square one. My returned stream is still reading zero bytes - so I need to investigate that some more first. I really appreciate your help so far. Thanks. – Matt Burland Oct 16 '14 at 15:51