Help! Axis WebサービスがC#アプリケーションで使用されています。長い値の配列が常に[0,0,0,0](右の長さ)として出てくるが、値はデシリアライズされません。私は他のプリミティブ(int、double)で試してみましたが、同じことが起こります。私は何をしますか?私は私のサービスのセマンティクスを変えたくありません。.NETがプリミティブ配列をWebサービスから非直列化しないのはなぜですか?
答えて
ここで私は結局何をしましたか。私はこれのためにそこに別の解決策を見つけたことはありませんので、もしあなたが何か良いものを持っていれば、是非貢献してください。
まず、WSDLの長い配列定義:タイプエリア:
<xsd:complexType name="ArrayOf_xsd_long">
<xsd:complexContent mixed="false">
<xsd:restriction base="soapenc:Array">
<xsd:attribute wsdl:arrayType="soapenc:long[]" ref="soapenc:arrayType" />
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
次に、我々は修正を行いますSoapExtensionAttributeを作成します。問題は、.NETがdouble値を含む要素に複数のIDを追いかけることがなかったことです。そこで、我々は値を探しに行く、配列項目を処理して、要素に値を挿入します。
[AttributeUsage(AttributeTargets.Method)]
public class LongArrayHelperAttribute : SoapExtensionAttribute
{
private int priority = 0;
public override Type ExtensionType
{
get { return typeof (LongArrayHelper); }
}
public override int Priority
{
get { return priority; }
set { priority = value; }
}
}
public class LongArrayHelper : SoapExtension
{
private static ILog log = LogManager.GetLogger(typeof (LongArrayHelper));
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return null;
}
public override object GetInitializer(Type serviceType)
{
return null;
}
public override void Initialize(object initializer)
{
}
private Stream originalStream;
private Stream newStream;
public override void ProcessMessage(SoapMessage m)
{
switch (m.Stage)
{
case SoapMessageStage.AfterSerialize:
newStream.Position = 0; //need to reset stream
CopyStream(newStream, originalStream);
break;
case SoapMessageStage.BeforeDeserialize:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = false;
settings.NewLineOnAttributes = false;
settings.NewLineHandling = NewLineHandling.None;
settings.NewLineChars = "";
XmlWriter writer = XmlWriter.Create(newStream, settings);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(originalStream);
List<XmlElement> longArrayItems = new List<XmlElement>();
Dictionary<string, XmlElement> multiRefs = new Dictionary<string, XmlElement>();
FindImportantNodes(xmlDocument.DocumentElement, longArrayItems, multiRefs);
FixLongArrays(longArrayItems, multiRefs);
xmlDocument.Save(writer);
newStream.Position = 0;
break;
}
}
private static void FindImportantNodes(XmlElement element, List<XmlElement> longArrayItems,
Dictionary<string, XmlElement> multiRefs)
{
string val = element.GetAttribute("soapenc:arrayType");
if (val != null && val.Contains(":long["))
{
longArrayItems.Add(element);
}
if (element.Name == "multiRef")
{
multiRefs[element.GetAttribute("id")] = element;
}
foreach (XmlNode node in element.ChildNodes)
{
XmlElement child = node as XmlElement;
if (child != null)
{
FindImportantNodes(child, longArrayItems, multiRefs);
}
}
}
private static void FixLongArrays(List<XmlElement> longArrayItems, Dictionary<string, XmlElement> multiRefs)
{
foreach (XmlElement element in longArrayItems)
{
foreach (XmlNode node in element.ChildNodes)
{
XmlElement child = node as XmlElement;
if (child != null)
{
string href = child.GetAttribute("href");
if (href == null || href.Length == 0)
{
continue;
}
if (href.StartsWith("#"))
{
href = href.Remove(0, 1);
}
XmlElement multiRef = multiRefs[href];
if (multiRef == null)
{
continue;
}
child.RemoveAttribute("href");
child.InnerXml = multiRef.InnerXml;
if (log.IsDebugEnabled)
{
log.Debug("Replaced multiRef id '" + href + "' with value: " + multiRef.InnerXml);
}
}
}
}
}
public override Stream ChainStream(Stream s)
{
originalStream = s;
newStream = new MemoryStream();
return newStream;
}
private static void CopyStream(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
}
最後に、我々が長い列をデシリアライズされますReference.csファイル内のすべてのメソッドにタグを付けます私たちの属性:
この修正は長いものですが、この問題が発生しているプリミティブ型を処理するために一般化される可能性があります。より良い代替手段を提供することがあり、このリンクが見つかり
は、ここで私は件名に書いたblog postの多かれ少なかれコピー、貼り付けたバージョンです。
要約:.NETが結果セットを逆シリアル化する方法(上記のChrisのソリューションを参照)を変更することも、.NET SOAP実装と互換性のある方法でAxisを再構成して結果をシリアル化することもできます。
あなたは後者のルートを行く場合は、ここに方法は次のとおりです。
...生成 クラスが見えると、通常 を機能するように見えるが、あなたは、クライアント に 非直列化された配列を見てみましょう場合 配列が逆シリアル化されており、 配列内のすべての値が0であることがわかります。 によって返されたSOAP応答を確認する必要があります。どうしましたか;あなたがAxisは が 返された要素に値を直接生成するが、ために代わり 参照外部要素ないことに気づくでしょう
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/>
<soapenv:Body>
<doSomethingResponse>
<doSomethingReturn>
<doSomethingReturn href="#id0"/>
<doSomethingReturn href="#id1"/>
<doSomethingReturn href="#id2"/>
<doSomethingReturn href="#id3"/>
<doSomethingReturn href="#id4"/>
</doSomethingReturn>
</doSomethingResponse>
<multiRef id="id4">5</multiRef>
<multiRef id="id3">4</multiRef>
<multiRef id="id2">3</multiRef>
<multiRef id="id1">2</multiRef>
<multiRef id="id0">1</multiRef>
</soapenv:Body>
</soapenv:Envelope>
: は、ここではサンプルの応答(再び、 を明確にするために編集)です 値。これは(と伝えのgSOAPと 古典的な.NETのWeb参照などもして)場合は、これが適切にWCF basicHttpBinding プロバイダによって処理さ ないものは何でも 比較的少数の離散値への多くの参照がある 感覚が、 を作るかもしれません。 次のパラメータ 編集Axisのデプロイメントの server-config.wsddファイルおよび見つける:falseに
<parameter name="sendMultiRefs" value="true"/>
変更して、 を
それは解決策を見つけるために私にしばらく時間がかかりましたコマンドラインで (Windowsでは)何か のように再デプロイしてください:
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient server-config.wsdl
Webサービスの 応答は、今あなたの.NETクライアントによって deserializableでなければなりません。
- 1. ジャクソンとのMoodle Webサービスからjsonを非直列化
- 2. 非プリミティブ配列
- 3. C#でJava WebサービスからSOAP応答を非直列化する
- 4. なぜプリミティブ型の配列はオブジェクトと見なされないのですか
- 5. 抽象基本クラスを直列化しないASMX Webサービス
- 6. Java変換不明なプリミティブ配列からオブジェクト配列へ
- 7. なぜこのWebサービスの配列から値を取得できないのですか?
- 8. Pickleがクラスの配列をシリアル化しないのはなぜですか?
- 9. JSONオブジェクトを.NETリストに非直列化
- 10. なぜJavaで抽象クラスを直列化しないのですか?
- 11. PHPオブジェクトの配列は、グローバル配列がそうしながら、直線的ではないのか?
- 12. Java内のすべての配列が直列化可能であるのはなぜですか?
- 13. C++でオブジェクト直列化が必要なのはなぜですか?
- 14. 配列の初期化後に配列の長さが正しくないのはなぜですか?
- 15. インデックスで直接配列にアクセスできないのはなぜですか?
- 16. カスケーディングするBaseOperationが直列化可能になるのはなぜですか?
- 17. RESTful Webサービスメソッドからプリミティブ配列を返す
- 18. 配列が残りの列を印刷しないのはなぜですか?
- 19. XMLからの非直列化時にリストプロパティが設定されない
- 20. なぜJsonオブジェクトの直列化を説明しますか?
- 21. JSONオブジェクトをTypescriptの配列で非直列化する
- 22. .NET WebサービスのXMLが他の人と異なるのはなぜですか?
- 23. 配列を直列化して逆直列化する方法
- 24. .NETで直列化できないオブジェクトをシリアライズする方法
- 25. この配列が空でないのはなぜですか?
- 26. オブジェクトを直列化解除した後、オブジェクトが他のオブジェクトを参照しないのはなぜですか?
- 27. なぜ部分的なデータの直列化にajaxが失敗しますか?
- 28. xmlを非直列化してオブジェクトを抽出しない
- 29. C#:バイト配列で初期化できないのはなぜですか?
- 30. malloc-ed配列と非malloc配列のサイズが異なるのはなぜですか?
魅力的なように機能しますが、生成されたコードを変更して属性を追加する必要があります – Luuk