Я пытался в течение нескольких дней теперь получить клиент.NET, работающий полностью с веб-сервером, обеспеченным моим находящимся в Coldfusion веб-приложением. Я не разработчик.NET, по сути, но у меня, оказывается, есть копия VS 2003, который кажется, что должен добиться цели.
Я могу использовать простой множитель () метод в моем веб-сервисе, который берет два числа и возвращает число, таким образом, простые типы хорошо работают. Это - составные типы, которые уничтожают меня. Я в основном пытаюсь возвратить ассоциативный массив из метода, названного get_struct (). Я возвращаю объект Карты типа, но свойство (названный объектом), который, как предполагается, является массивом с двумя элементами (типа mapItem) всегда, имеет "неопределенное значение".
Вот WSDL, который сгенерирован ColdFusion:
This is a collection of test methods to allow remote developers
to evaluate datatype support, etc in their programming environment.
The WSDL endpoint for this web service is [YOUR PEERFOCUS SITE]/remote_api/pfapi/v/trunk/remote_io_test.cfc?wsdl
и вот тупик веб-сервиса, сгенерированный, когда я добавляю веб-ссылку в VS:
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
// Runtime Version: 1.1.4322.2443
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
//
// This source code was auto-generated by Microsoft.VSDesigner, Version 1.1.4322.2443.
//
namespace pfapi_test.remote_io_test {
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Services;
///
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="remote_io_test.cfcSoapBinding", Namespace="http://trunk.v.pfapi.remote_api")]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(QueryBean))]
[System.Xml.Serialization.SoapIncludeAttribute(typeof(CFCInvocationException))]
public class remote_io_testService : System.Web.Services.Protocols.SoapHttpClientProtocol {
///
public remote_io_testService() {
this.Url = "http://leon.cupahr.tafkan.nooch/remote_api/pfapi/v/trunk/remote_io_test.cfc";
}
///
[System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://trunk.v.pfapi.remote_api", ResponseNamespace="http://trunk.v.pfapi.remote_api")]
[return: System.Xml.Serialization.SoapElementAttribute("multiplierReturn")]
public System.Double multiplier(System.Double factor1, System.Double factor2) {
object[] results = this.Invoke("multiplier", new object[] {
factor1,
factor2});
return ((System.Double)(results[0]));
}
///
public System.IAsyncResult Beginmultiplier(System.Double factor1, System.Double factor2, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("multiplier", new object[] {
factor1,
factor2}, callback, asyncState);
}
///
public System.Double Endmultiplier(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((System.Double)(results[0]));
}
///
[System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://trunk.v.pfapi.remote_api", ResponseNamespace="http://trunk.v.pfapi.remote_api")]
[return: System.Xml.Serialization.SoapElementAttribute("get_structReturn")]
public Map get_struct() {
object[] results = this.Invoke("get_struct", new object[0]);
return ((Map)(results[0]));
}
///
public System.IAsyncResult Beginget_struct(System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("get_struct", new object[0], callback, asyncState);
}
///
public Map Endget_struct(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((Map)(results[0]));
}
///
[System.Web.Services.Protocols.SoapRpcMethodAttribute("", RequestNamespace="http://trunk.v.pfapi.remote_api", ResponseNamespace="http://trunk.v.pfapi.remote_api")]
[return: System.Xml.Serialization.SoapElementAttribute("struct_keycountReturn")]
public System.Double struct_keycount(Map theStruct) {
object[] results = this.Invoke("struct_keycount", new object[] {
theStruct});
return ((System.Double)(results[0]));
}
///
public System.IAsyncResult Beginstruct_keycount(Map theStruct, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("struct_keycount", new object[] {
theStruct}, callback, asyncState);
}
///
public System.Double Endstruct_keycount(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((System.Double)(results[0]));
}
}
///
[System.Xml.Serialization.SoapTypeAttribute("Map", "http://xml.apache.org/xml-soap")]
public class Map {
///
public mapItem[] item;
}
///
[System.Xml.Serialization.SoapTypeAttribute("mapItem", "http://xml.apache.org/xml-soap")]
public class mapItem {
///
public object key;
///
public object value;
}
///
[System.Xml.Serialization.SoapTypeAttribute("QueryBean", "http://rpc.xml.coldfusion")]
public class QueryBean {
///
public string[] columnList;
///
public object[] data;
}
///
[System.Xml.Serialization.SoapTypeAttribute("CFCInvocationException", "http://rpc.xml.coldfusion")]
public class CFCInvocationException {
}
}
И наконец, мое приложение CLI, которое тестирует сервис:
using System;
namespace pfapi_test
{
///
/// Summary description for Class1.
///
class Class1
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Console.WriteLine("Instantiating WS");
remote_io_test.remote_io_testService testWS = new remote_io_test.remote_io_testService();
Console.WriteLine("Calling multiplier(3,15)");
Console.WriteLine(testWS.multiplier(3,15));
Console.WriteLine("Calling get_struct()");
remote_io_test.Map theStruct = testWS.get_struct();
Console.Write("result: ");
Console.WriteLine(theStruct);
Console.Write("result.item: ");
Console.WriteLine(theStruct.item);
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
}
Независимо от того, что я пробую, theStruct.item всегда является "неопределенным значением" согласно отладчику. Печатный вывод похож:
Instantiating WS
Calling multiplier(3,15)
45
Calling get_struct()
result: pfapi_test.remote_io_test.Map
result.item:
Press Enter to exit...
Я попытался использовать ColdFusion 8, и нет никакого различия. Я попытался возвратить реальную пользовательскую базу данных с двумя свойствами вместо моего специального ассоциативного массива, и это хорошо работает, но перезапись моего API для предотвращения ассоциативных массивов не является действительно опцией в это время. API хорошо работает с ColdFusion, PHP/NuSOAP и Ruby on Rails, таким образом, кажется, что должно быть возможно получить его работающий с.NET также.
Я надеюсь, что кто-то может обеспечить некоторое понимание. У меня есть подозрение, что существует некоторая проблема пространства имен здесь, но я не знаю, что SOAP и XML достаточно хорошо выясняют, каково это. Я также искал как безумный решение онлайн, но я не нашел единственного человека, который решил эту проблему, которая очень приводит в уныние!
Запрос:
POST /remote_api/pfapi/v/trunk/remote_io_test.cfc HTTP/1.1
VsDebuggerCausalityData: [snip]
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.1.4322.2443)
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 488
Expect: 100-continue
Host: leon.cupahr.tafkan.nooch
Ответ:
HTTP/1.1 200 OK
Date: Thu, 17 Dec 2009 15:14:33 GMT
Server: Apache/2.2.11 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.7l DAV/2 PHP/5.2.8 JRun/4.0 Phusion_Passenger/2.2.7
Set-Cookie: CFID=21543;expires=Sat, 10-Dec-2039 15:14:33 GMT;path=/
Set-Cookie: CFTOKEN=479cc311ca4875db-9D346355-ED36-6183-C8895635E4EE1252;expires=Sat, 10-Dec-2039 15:14:33 GMT;path=/
Transfer-Encoding: chunked
Content-Type: text/xml; charset=utf-8
-
FOO
bar
-
ANOTHERKEY
another value
Обновление: Я получил известие от разработчика.NET на другом конце, и он попробовал все следующие напрасно:
Он действительно отправлял мне снимок экрана раздела "Data Type" Сервисного Ссылочного диалогового окна Настроек. Действительно ли возможно, что изменение настроек для типа Набора и типа набора Словаря могло бы решить этот вопрос?
Обновление 2: вот код ColdFusion для remote_io_test.cfc
Спасибо за чтение и заранее спасибо за Ваши ответы!
Перекрестно разосланный в тексте ссылки
Я не очень понимаю вопрос. В State Design образца совершенно ясно. См. книгу узоров проектирования .
class SuperState( object ):
def someStatefulMethod( self ):
raise NotImplementedError()
def transitionRule( self, input ):
raise NotImplementedError()
class SomeState( SuperState ):
def someStatefulMethod( self ):
actually do something()
def transitionRule( self, input ):
return NextState()
Это довольно распространенный образец, используемый в Java, C++, Python (и я уверен, что другие языки, также).
Если ваши правила перехода состояния оказываются тривиальными, есть некоторые оптимизации, чтобы переместить само правило перехода в суперкласс.
Обратите внимание, что мы должны иметь прямые ссылки, поэтому мы ссылаемся на классы по имени и используем eval
для перевода имени класса в фактический класс. Альтернативой является создание переменных экземпляра правил перехода вместо переменных класса, а затем создание экземпляров после определения всех классов.
class State( object ):
def transitionRule( self, input ):
return eval(self.map[input])()
class S1( State ):
map = { "input": "S2", "other": "S3" }
pass # Overrides to state-specific methods
class S2( State ):
map = { "foo": "S1", "bar": "S2" }
class S3( State ):
map = { "quux": "S1" }
В некоторых случаях ваше событие не так просто, как проверка объектов на равенство, поэтому более общим правилом перехода является использование правильного списка пар «функция-объект».
class State( object ):
def transitionRule( self, input ):
next_states = [ s for f,s in self.map if f(input) ]
assert len(next_states) >= 1, "faulty transition rule"
return eval(next_states[0])()
class S1( State ):
map = [ (lambda x: x == "input", "S2"), (lambda x: x == "other", "S3" ) ]
class S2( State ):
map = [ (lambda x: "bar" <= x <= "foo", "S3"), (lambda x: True, "S1") ]
Поскольку правила вычисляются последовательно, это позволяет использовать правило «по умолчанию».
-121--1117091-Я нашел ответ:
f.object.id
-121--2695363- Не используйте структуры Coldfusion в вашей веб-службе.
Как и все до нас, мы отказались и переписали наш API, чтобы не использовать ассоциативные массивы в запросе или ответе. Теперь мы используем скаляры, массивы и complexTypes, которые автоматически создаются из CFC. На этот раз мы проверили нашу концепцию с PHP, Ruby, Coldfusion, Java и .NET, чтобы убедиться, что она действительно совместима.
Сейчас имеет большой смысл, что статически типизированный язык не сможет обрабатывать полностью произвольный удаленный тип данных в любом разумном пути.
Спасибо за все ваши отзывы!
Я сам боролся с этим пунктом со стороны .NET клиента - я пытаюсь использовать веб-сервис, написанный на ColdFusion. Из документации, которую я нашел, тип данных структуры в ColdFusion не отображается непосредственно на какие-либо типы веб-сервисов, и мне кажется, что это вина Axis.
Вы, вероятно, читали те же самые веб-страницы, что и я, когда пытался решить эту проблему, но если вы хотите создать веб-сервис с помощью ColdFusion, рекомендую не использовать тип структуры. Если ваш веб-сервис еще не жив, и вы можете уйти от использования чего-то другого, я бы посоветовал пойти по этому пути. Я попробовал вернуть объекты из ColdFusion, которые отлично работали для меня от клиента .NET.
На самом деле я отказался от этой проблемы и написал пользовательский клиент для моей .NET программы, который просто прочитал бы Xml, возвращенный веб-сервисом ColdFusion, и преобразовал бы его в словарь, так как я не имею никакого влияния на сервис, который я пытаюсь вызвать.
Одна вещь, которую я нашел во время моего тестирования - сервис, который я пытаюсь вызвать, работает на более старой версии ColdFusion (7, на мой взгляд). Всякий раз, когда я звоню в этот сервис, .NET клиент возвращает ноль. Я установил ColdFusion на свою машину и написал простой сервис, и обнаружил, что .NET клиент вернул объект типа Map (который пришел из WSDL), но все свойства объекта Map были нулевыми.
Мне было бы интересно посмотреть, решит ли проблему предложение Криса Хааса в комментариях к вашему вопросу об установке dotNetSoapEncFix.
.