Let's be honest here - the fault was all mine although it took a long time to realize why.
This isn't really a WPF issue at all, but it is a WCF issue and I'm only using WCF because the client is in WPF. The question is "How do I tell Reporting Services to render a report and return the pdf to me so I can send it back to the client?" I have a WCF service doing this so I can take more control over parameters, security, etc.
There's dozens of ways to do this and I explored most of them. The one that made most sense to me was to create a web request object and grab the response in a web response. Then I save the ResponseStream to a temporary file which gives me the option to dynamically stitch a bunch of reports together using ExpertPDF and return a single pdf file to the client as a byte array.
You have to be very careful to use the correct methods and understand how they work. For example, System.IO.File.ReadToEnd returns a string which can cause pdf files (which can be binary) to be corrupted. Also Stream.Read does not necessarily read all the bytes you asked for. You have to keep calling it until the stream is fully read.
If you only execute a single call to Stream.Read you may not completely populate the byte array - and your pdf file will be corrupted.
Here's the code to execute a report and save it to a temporary file...
Public Function RunReportingServicesReport() As String
Dim URL As String
Dim Request As System.Net.HttpWebRequest = Nothing
Dim Response As System.Net.HttpWebResponse = Nothing
Dim ReportName As String = Nothing
Dim Stream As System.IO.Stream = Nothing
Dim Bytes As Byte()
Dim BytesRead As Integer = 0
Dim BytesToRead As Integer
Dim Offset As Integer = 0
Try
URL = "http://ReportServer/ReportService?/Reports/MyReport&rs:Format=PDF&rs:Command=Render"
Request = System.Net.WebRequest.Create(URL)
Request.PreAuthenticate = True
Request.Credentials = New System.Net.NetworkCredential("User", "Password", "Domain")
Response = Request.GetResponse()
ReportName = System.IO.Path.GetTempFileName()
Stream = Response.GetResponseStream()
BytesToRead = Response.ContentLength
Bytes = New Byte(BytesToRead - 1) {}
Do While BytesToRead > 0
BytesRead = Stream.Read(Bytes, Offset, BytesToRead)
Offset += BytesRead
BytesToRead -= BytesRead
Loop
System.IO.File.WriteAllBytes(ReportName, Bytes)
Catch ex As System.Exception
Throw New System.Exception("RunReportingServicesReport:" & ex.Message)
Finally
If Stream IsNot Nothing Then Stream.Close()
If Response IsNot Nothing Then Response.Close()
End Try
Return ReportName
End Function