Попытка вызвать службу WCF с помощью WebRequest

У меня есть служба WCF, которую нужно вызывать сторонним приложением, публикуя необработанный XML.

Я пытаюсь протестировать свою службу, создав простой WebRequest и отправив запрос в службу.

Вот мой сервисный код:

Интерфейс:

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

Услуга:

    [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);
    }
}

конфигурация:

    <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>

неверный код клиента:

            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();

В этой последней строке я получаю ошибку 400 (неверный запрос) или 415 (неподдерживаемый тип носителя), в зависимости от того, какой ContentType я указываю.

Кроме того, если я добавлю ссылку на службу в свое клиентское приложение и вызову службу с помощью API, она будет работать нормально. Буду очень признателен за любые идеи, так как я новичок в WCF и полностью озадачен.


person Seth    schedule 04.03.2010    source источник
comment
Что бы я сделал: использовал Fiddler fiddler2.com/fiddler2, чтобы увидеть запрос API - тот, который работает. Затем сравните его с запросом, который не работает. Это должно сузить его.   -  person Cheeso    schedule 04.03.2010
comment
Ваш StreamReader должен находиться в блоке using, как и несколько других ваших объектов. Блок using приведет к тому, что они будут удалены, даже если возникнет исключение.   -  person John Saunders    schedule 05.03.2010


Ответы (2)


Я думаю, что вы смешиваете две разные вещи здесь:

  1. WebRequest и POST, и атрибут [WebInvoke] предполагают, что вы пытаетесь сделать что-то вроде REST
  2. Однако в конфигурации вашего сервиса есть basicHttpBinding — протокол SOAP, который не работает с WebRequest.

Так что - решайтесь!

Вы хотите использовать SOAP? Тогда у вас все в порядке с basicHttpBinding как есть, но вы не можете получить доступ к службе SOAP точно так же из WebRequest с POST - вам нужно использовать клиент SOAP, сгенерированный Visual Studio, или svcutil.exe в командной строке.

Вы хотите использовать WebRequest и простой POST-запрос?? Затем вам нужно создать службу WCF на основе REST - используйте webHttpBinding и WebServiceHost (в отличие от простого ServiceHost).

Службы WCF на базе SOAP см. в Центре разработчиков WCF на сайте MSDN.

Для служб WCF на основе REST (к которым вы можете перейти в своем браузере и которые вы можете вызвать из WebRequest), ознакомьтесь с WCF REST Developer Center на MSDN и посмотрите превосходную серия скринкастов от Pluralsight о разработке на основе REST в WCF, в частности:

person marc_s    schedule 04.03.2010
comment
Центр разработчиков WCF кажется мертвым - доступна ли какая-либо обновленная ссылка? - person Default; 08.08.2017
comment
.. К сожалению, и видео RESTful. - person Default; 08.08.2017
comment
@Default: извините, эти ссылки были в порядке - в 2010, когда я ответил, - но вы правы, они, кажется, мертвы. Извините, у меня нет альтернативных ссылок..... попробуйте спросить у Google или Bing, может быть?? - person marc_s; 08.08.2017
comment
Я знаю, что вы написали ответ в 2010 году. Не нужно его указывать. Когда ссылки гниют в stackoverflow, я обычно сообщаю об этом OP, поскольку я не просто хочу случайным образом обновлять ссылки на какой-либо другой ресурс. Мое намерение состояло в том, чтобы как-то обновить ссылки и для других посетителей, а не только сейчас для меня. Мне жаль, если вы обиделись. Я попробую Гугл. - person Default; 08.08.2017

BasicHttpBinding тоже подходит!

Я потратил почти день, выясняя, что не так с сервисом WebRequest to WCF с basicHttpBinding, и оказалось, что я упустил маленькую, но важную вещь: должен быть установлен заголовок SOAPAction!

newRequest.Headers["SOAPAction"] = "http://tempuri.org/INotificationService/MyMethodName"
person ADOConnection    schedule 17.07.2012
comment
Что вы поставляли в теле WebRequest. Включал ли он также SOAPHeaders. - person Abhijeet; 21.08.2013
comment
@autrevo, ты имеешь в виду поток запросов? Вы можете установить http-прокси (например, Fiddler) и проверить, что отправляется в вызове службы WCF. Вы увидите тело запроса и заголовки. Мне пришлось переслать запрос в моей задаче, поэтому я не строю тело запроса самостоятельно. - person ADOConnection; 22.08.2013