У моего приложения есть собственный язык сценариев, от которого я не могу избавиться (написано много пользовательских сценариев).Теперь мои клиенты спрашивают, можно ли вызвать сервис SOAP из этого языка сценариев.Конечно, сервис SOAP, который необходимо вызвать, будет отличаться для каждого клиента.Это оставляет мне несколько вариантов:
- Использование утилиты WSDL для генерации клиентских прокси-серверов SOAP и помещения специфичной для клиента логики в мое приложение
- Использование утилиты WSDL для генерацииКлиентские прокси-серверы SOAP, ориентированные на клиента, помещают клиентскую логику в специфичные для клиента DLL-библиотеки и предусматривают систему плагинов, в которой приложение может вызывать плагин универсальным образом
- Создать универсальный модуль, который динамическигенерирует вызов SOAP
Первые 2 варианта не являются реальной альтернативой в моем случае, так как я не хочу никакой пользовательской логики в приложении или пользовательских DLL.
Для меня третий вариант, в долгосрочной перспективе, является лучшим, поскольку он позволяет моим коллегам-консультантам вызывать службу SOAP через мой язык сценариев без каких-либо специфических для клиента разработок.Динамическое добавление функций к моему языку сценариев не является проблемой, генерация динамического вызова SOAP:
Я начал с просмотра вывода утилиты WSDL.Потом я начал убирать вещи, пока они больше не работали.Следующий фрагмент кода по-прежнему работает:
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"wsdl", L"4.0.30319.1"),
System::Diagnostics::DebuggerStepThroughAttribute,
System::ComponentModel::DesignerCategoryAttribute(L"code"),
System::Web::Services::WebServiceBindingAttribute(Name=L"MyOwnScriptingSoapClient", Namespace=L"http://microsoft.com/webservices/")]
public ref class MyWebService : public System::Web::Services::Protocols::SoapHttpClientProtocol
{
public:
MyWebService() {}
public:
[System::Web::Services::Protocols::SoapDocumentMethodAttribute(L"http://microsoft.com/webservices/GetPrimeNumbers", RequestNamespace=L"http://microsoft.com/webservices/",
ResponseNamespace=L"http://microsoft.com/webservices/", Use=System::Web::Services::Description::SoapBindingUse::Literal, ParameterStyle=System::Web::Services::Protocols::SoapParameterStyle::Wrapped)]
System::String^ GetPrimeNumbers(System::Int32 max);
};
inline System::String^ MyWebService::GetPrimeNumbers(System::Int32 max) {
cli::array< System::Object^ >^ results = this->Invoke(L"GetPrimeNumbers", gcnew cli::array< System::Object^ >(1) {max});
return (cli::safe_cast<System::String^ >(results[0]));
}
URL-адрес веб-службы может быть динамическим путем установки свойства Url, но я не могу найти способ сделать имя метода динамическим.
Добавление общего метода, подобного этому, по-прежнему работает:
...
[System::Web::Services::Protocols::SoapDocumentMethodAttribute(L"http://microsoft.com/webservices/GetPrimeNumbers", RequestNamespace=L"http://microsoft.com/webservices/",
ResponseNamespace=L"http://microsoft.com/webservices/", Use=System::Web::Services::Description::SoapBindingUse::Literal, ParameterStyle=System::Web::Services::Protocols::SoapParameterStyle::Wrapped)]
cli::array< System::Object^ >^ CallWs(cli::array< System::Object^ >^ args);
...
inline cli::array< System::Object^ >^ MyWebService::CallWs(cli::array< System::Object^ >^ args) {
cli::array< System::Object^ >^ results = this->Invoke(L"GetPrimeNumbers", args);
return results;
Но как только я удаляю метод GetPrimeNumbers, вызов больше не работает и выдает следующую ошибку:
Unhandled Exception: System.ArgumentException: GetPrimeNumbers Web Service method name is not valid.
at System.Web.Services.Protocols.SoapHttpClientProtocol.BeforeSerialize(WebRequest request, String methodName, Object[] parameters)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at MyWebService.CallWs(Object[] args)
at main(Int32 argc, SByte** argv)
at _mainCRTStartup()
Кроме того, изменение имени веб-службы в атрибуте SoapDocumentMethodAttribute (например, на GetPrimo) выдает такую же ошибку.
Поэтому мои вопросы:
- Есть ли смысл продолжать идти по этому пути, то есть смотреть на сгенерированную WSDL-логику, пытаясь «обобщить» вызов (любой) службы SOAP, или это просто никогда не сработает?
- Есть ли другие хорошие способыгенерации вызова SOAP динамическим способом (с использованием .Net)?
- Или это единственный метод для создания XML (Soap Envelope) самостоятельно для выполнения вызова SOAP?
- Есть ли шансеПример кода, над которым я могу продолжать работать?
Заранее спасибо, Патрик