views:

913

answers:

1

I have a WCF service that needs to be called by a 3rd party app, posting some raw XML.

I am trying to test my service by constructing a simple WebRequest and making the request to the service.

Here's my service code:

Interface:

    [ServiceContract(Namespace = "http://test.mydomain.com")]
public interface ITest
{
    [WebInvoke(UriTemplate = "", BodyStyle = WebMessageBodyStyle.Bare, Method="POST")]
    [OperationContract]
    Stream SaveXML(Stream input);
}

Service:

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(Namespace = "http://test.mydomain.com")]
public class Test : ITest
{
    public Stream SaveXML(Stream input)
    {
        StreamReader streamReader = new StreamReader(input);
        string rawString = streamReader.ReadToEnd();
        streamReader.Dispose();

        // here need to save the input stream to xml format file
        Encoding encoding = Encoding.GetEncoding("ISO-8859-1");
        WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
        byte[] returnBytes = encoding.GetBytes(rawString);
        return new MemoryStream(returnBytes);
    }
}

config:

    <services>
  <service behaviorConfiguration="Blah.TestBehavior" name="Blah.Test">
    <endpoint address="http://localhost:51494/Blah/Test.svc" binding="basicHttpBinding" contract="Blah.ITest">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>

faulty client code:

            string postData = "<Message version=\"1.5\" xmlns=\"http://test.mydomain.com\" ><books>Blah</books></Message>";
        WebRequest request = WebRequest.Create("http://localhost:51494/Blah/Test.svc/SaveXML");
        request.Method = "POST";

        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        request.ContentType = "application/x-www-form-urlencoded";
        //request.ContentType = "text/xml; charset=utf-8";
        //request.ContentType = "text/xml;";
        //request.ContentType = "application/xml;";
        request.ContentLength = byteArray.Length;

        Stream dataStream = request.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();

        // Get the response.
        WebResponse response = request.GetResponse();

On that last line I get a 400 (Bad Request) or 415 (Unsupported Media Type) error, depending on which ContentType I specify.

Also, if I add a service reference in my client app, and call the service using the API it works fine. Any insights would be greatly appreciated, as I am new to WCF and completely stumped.

+1  A: 

I think you're mixing up two different things here:

  1. WebRequest and a POST and the [WebInvoke] attribute suggests you're trying to do something like REST
  2. Your service config however has basicHttpBinding - a SOAP protocol which won't fly with WebRequest

So - make up your mind!

Do you want to use SOAP? Then you're fine with the basicHttpBinding as is, but you cannot access a SOAP service just like that from a WebRequest with POST - you need to use the SOAP client generated by Visual Studio or svcutil.exe on the command line.

Do you want to use WebRequest and a simple POST request?? Then you need to create a REST based WCF service - use the webHttpBinding and the WebServiceHost (as opposed to a plain ServiceHost).

For SOAP-based WCF services, check out the WCF Developer Center on MSDN.

For REST-based WCF services (which you can navigate to in your browser, and which you can call from WebRequest), check out the WCF REST Developer Center on MSDN and have a look at the excellent screencast series by Pluralsight on REST based development in WCF - most notably:

marc_s