2012-05-15 2 views
3

Я пытаюсь протестировать службу WCF без создания WCF-клиента. У меня есть аналогичный код/​​проблемы, как представлено here.вызов служб WCF с использованием SOAP

Я хочу полностью контролировать полезную нагрузку SOAP, поэтому я хочу иметь возможность отправлять свои собственные веб-запросы/ответы и подставлять свой собственный XML в качестве параметров в любой метод. Я также хочу, чтобы возвращаемый SOAP XML был точно таким, как есть, без создания объектов ответа, объектов исключения объектов и т. Д.

Как точка отсчета, я хочу сделать то, что делает SoapUI в точке, которую вы нажимаете на кнопку выполнения и верните ответ. Я предполагаю, что SoapUI НЕ создает клиента WCF, строит запрос и вызывает этот метод, а скорее выдает полный SOAP-вызов службе WCF и отображает результат.

В ответ на вопросы, приведенные в комментариях, причина, по которой я не хочу создавать WCF-клиент, заключается в том, что я хочу быть изолированным от любых изменений в сервисе, не нужно пересобирать ссылки, изменять свои собственные код, создать отдельный код для каждого нового сервиса/метода и т. д., потому что этот процесс автоматически запускается после каждой сборки без взаимодействия.

Итак, у меня есть сотни тысяч тестовых XML-параметров, которые я передаю в сотни методов, не заботясь о том, что они собой представляют. Мы много лет работаем над веб-сервисами ASMX, и один метод (очень похожий на приведенную выше ссылку) обрабатывает все веб-сервисы/методы/параметры тестирования.

С переходом на WCF я получаю ошибки внутреннего сервера, особенно при тестировании недействительных узлов XML: отсутствуют необходимые узлы, ошибки в методе создания для повторяющихся имен и т. Д. (Любое условие ошибки). Я думаю, что имеет смысл, что есть простой способ сделать это с WCF таким же образом.

Я хочу ТОЧНО, что SoapUI отправляет обратно, мне просто нужно знать, как это делается.

+0

Я не уверен, что вы имеете в виду. Вызов выполняется путем отправки SOAP XML с помощью веб-запроса POST, как и вы сказали. WCF позаботится о сериализации и уровне веб-запросов/ответов. – lockstock

+0

@s mac: Я предлагаю вам объяснить, что вы пытаетесь сделать, а не то, как вы в настоящее время пытаетесь. Удалите все ваши комментарии и вместо этого создайте простой, сжатый вопрос. Вы упомянули, что вы тестер. Вы хотите протестировать веб-службу WCF и хотите полностью контролировать полезную нагрузку SOAP. Это оно? Почему вы хотите сделать это на низком уровне, вместо использования WCF-клиента или SoapUI? – JohnDoDo

+0

ОК, Джон ... Я снова попытался. Поскольку я не хорошо разбираюсь в WCF или SOAP, это единственный способ узнать, как это объяснить. Я уверен, что есть очевидный способ сделать это (вам и другим), я просто не знаю, что это такое, и я искал дни. Если у вас есть еще вопросы, сообщите мне. Благодарю. –

ответ

3

@John Saunders верен в своем комментарии. Что бы вы ни делали с ASMX, вы должны иметь возможность делать с WCF. На самом деле не имеет значения, какая структура/технология использует ваш веб-сервис, если вы выполняете правильный запрос SOAP.

WCF - это всего лишь основа, которая помогает создавать ориентированные на обслуживание приложения. Как и любые другие структуры такого рода, он позволяет сосредоточиться на фактическом сервисе, который вы предоставите, заботясь о всех функциях сантехники, необходимых для предоставления этой услуги в качестве веб-службы SOAP.

Что касается SoapUI, то это инструмент Java, который позволяет тестировать веб-службы. Когда вы кормите его WSDL, it dynamically creates запросите образцы, которые затем отправляются на веб-службу с (если я не ошибаюсь) Http Client.

Ничего необычного, если у вас есть веб-сервис WCF. Это по-прежнему SOAP связи, что вы можете сделать даже с основным клиентом, как это:

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     // OK, this is not a WCF web service, but that should not matter :D 
     string endpoint = "http://www.html2xml.nl/Services/Calculator/Version1/Calculator.asmx"; 

     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endpoint); 
     request.ContentType = "text/xml"; // or application/soap+xml for SOAP 1.2 
     request.Method = "POST"; 
     request.KeepAlive = false; 

     //In case you have a proxy to resolve the server name also add these lines 
     var proxyServer = new WebProxy("XX.XX.XX.XX", 1234); 
     proxyServer.Credentials = CredentialCache.DefaultCredentials; // or username + password 
     request.Proxy = proxyServer; 

     // you can read these from files 
     string payload = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/""> 
           <soapenv:Header/> 
           <soapenv:Body> 
            <tem:Add> 
            <tem:a>1</tem:a> 
            <tem:b>2</tem:b> 
            </tem:Add> 
           </soapenv:Body> 
          </soapenv:Envelope>"; 

     byte[] byteArray = Encoding.UTF8.GetBytes(payload); 
     request.ContentLength = byteArray.Length; 

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

     HttpWebResponse response = null; 
     try 
     { 
      response = (HttpWebResponse)request.GetResponse(); 
     } 
     catch (WebException ex) 
     { 
      response = (HttpWebResponse)ex.Response; 
     } 

     Console.WriteLine(string.Format("HTTP/{0} {1} {2}\n", response.ProtocolVersion, (int)response.StatusCode, response.StatusDescription)); 

     // you can write this to files 
     Stream responseStream = response.GetResponseStream(); 
     StreamReader reader = new StreamReader(responseStream); 
     Console.WriteLine(reader.ReadToEnd()); 

     // cleanp 
     reader.Close(); 
     requestStream.Close(); 
     responseStream.Close(); 
     response.Close(); 
    } 
} 

Вы получаете обратно ответ SOAP, в данном случае это:

HTTP/1.1 200 OK 

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <soap:Body> 
     <AddResponse xmlns="http://tempuri.org/"> 
      <AddResult>3</AddResult> 
     </AddResponse> 
    </soap:Body> 
</soap:Envelope> 

и это не имеет значения, если это было ASMX, который сгенерировал его, или WCF или что-то еще. Это ответ на HTTP-запрос.

Если вместо того, чтобы вы отправить недопустимое сообщение, как:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <tem:Add> 
     <tem:a>x</tem:a> 
     <tem:b>y</tem:b> 
     </tem:Add> 
    </soapenv:Body> 
</soapenv:Envelope> 

вы получите обратно ошибку, что-то вроде:

HTTP/1.1 500 Internal Server Error 

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <soap:Body> 
     <soap:Fault> 
      <faultcode>soap:Client</faultcode> 
      <faultstring> ... exception stacktrace here ... </faultstring> 
      <detail /> 
     </soap:Fault> 
    </soap:Body> 
</soap:Envelope> 

Вы можете automate the tests with SoapUI или даже интегрировать их с Junit, вы могли бы даже используйте что-то вроде JMeter, который хотя и не предназначен специально для веб-сервисов (например, SoapUI) it can test SOAP. И вы можете использовать этот базовый клиент, который я добавил в свой ответ.

+0

спасибо за ответ, и я согласен. Он должен работать одинаково. Но это не так. Даже с вашим кодом я получаю тот же результат. Если у меня есть «случай успеха», он работает нормально. Но если я получу какой-либо тип ошибки (недопустимые данные, неправильное состояние, неспособность выполнить операцию по какой-либо причине и т. Д.), Я получаю (500) - Внутреннюю ошибку сервера. Я пробовал все примеры, которые я видел. Поскольку SoapUI способен копировать вызовы и возвращать ошибки в ответе, я предполагаю, что ошибка где-то моя. Но спасибо. Несмотря на то, что это не помогло мне, это помогло мне понять. –

+0

@s mac: Я добавил несколько подробностей к моему ответу (в основном строки перед 'Console.WriteLine (string.Format (" HTTP/{0} {1} {2} \ n "...'. Скажите мне если теперь вы можете получить ошибку SOAP из ответа 500 HTTP. – Bogdan

+0

это была моя проблема. Я набрал ответ, когда вы разместили это, я думаю. Но, да, спасибо. Я просто не знал, как обращаться с WebException. –

0

ответ на этот вопрос, вероятно, был очевидным для всех, кроме меня ... но вот он: я получал ошибку (500) Internal Server и не знал, что с ней делать. Оказывается, опять же, очевидно, очевидно для всех, что вы должны поймать ошибку WebException. В WebException есть ответ, который вы можете использовать для получения условия сбоя, полного ответа и т. Д. Я выбрал исключение, но не специально для WebException. Извините, если я смутил кого-то, но у меня были проблемы, когда у меня возникали ошибки, в противном случае все образцы кода (даже мои оригиналы) работали.

Я думаю, я мог бы опубликовать это как еще один вопрос, но является ли это типичным поведением? Даже для ошибки, такой же простой, как попытка создать дублируемую запись/элемент, недопустимое имя и т. Д. Вызывается WebException? Я уверен, из-за отсутствия опыта, я ожидал, что ответ об ошибке вернется таким же образом, как и ответ успеха без внутренней ошибки сервера, и без необходимости улавливать WebException вне службы (за исключением случаев, когда это действительно было исключение «web»).

Спасибо за все ваши ответы.

+1

Вы получаете исключение всякий раз, когда веб-запрос не может быть успешно выполнен. Иногда может возникнуть неприятность в обработке исключения, но альтернатива не лучше, а именно проверка кода статуса 200 после каждого запроса. Обычно ваш код имеет два пути выполнения: по успеху и при неудаче. Обработчик ошибок обычно является более чистым способом обработки пути «при сбое» – Bogdan

Смежные вопросы