Web サービス経由で複雑なデータを送信するための好ましい方法は何ですか?
-
08-06-2019 - |
質問
2008年のことですが、私はまだこの件について悩んでいます。そこで、複雑な型を渡したり返したりする必要がある Web メソッドを開発しています。私が検討している 2 つのオプションは次のとおりです。
渡して戻る 実際の データと動作の両方を含むビジネス オブジェクト。wsdl.exe を実行すると、データ部分のみを含むプロキシ クラスが自動的に作成され、これらはサーバー側で実際のビジネス オブジェクトとの間で自動的に変換されます。クライアント側では、ダム プロキシ タイプのみを使用できるようになり、適切と思われる実際のビジネス オブジェクトにそれらをマッピングする必要があります。ここでの大きな欠点は、サーバー側とクライアント側の両方を「所有」しており、実際のビジネス オブジェクトの同じセットを使用したい場合、名前の競合などの問題が発生する可能性があることです。(実際のオブジェクトとプロキシの名前が同じであるため)。
「実際の」ビジネス オブジェクトを渡そうとすることは忘れてください。代わりに、実際のビジネス オブジェクトに手動でマッピングする単純な DataTransfer オブジェクトを作成するだけです。いずれにせよ、それらは依然として wsdl.exe によって新しいプロキシ オブジェクトにコピーされますが、少なくとも私は、Web サービスがビジネス ロジックを含むオブジェクトをネイティブに処理できると考えているつもりはありません。
ところで、誰かがwsdl.exeに次のことを指示する方法を知っていますか? ない オブジェクトのコピーを作成しますか?「ねえ、ここにあるこの既存のタイプを使用してください」と伝えることができるべきではないでしょうか。真似しないでください!」
とりあえず、#2 に落ち着きましたが、皆さんのご意見が気になります。あるような気がする 方法 一般的にこれを行うためのより良い方法はありますが、私がすべての点で完全に正確であるとは限りませんので、あなたの経験を教えてください。
アップデート:VS 2008 には、「サービス参照」を追加するときに、プロキシ ファイルにまったく新しい同一の型を作成するのではなく、既存の型を再利用するオプションがあることを知りました。甘い。
解決
層を分離するための議論もあります。Web サービスとの間で受け渡されるシリアル化可能なオブジェクトのセットと、そのセットとビジネス オブジェクト (オブジェクトの受け渡しに適さないプロパティを持つ可能性がある) の間でマッピングおよび変換するトランスレーターが必要です。ワイヤー)
これは、Web サービス ソフトウェア ファクトリが好むアプローチです サービス工場 これは、Web サービス インターフェイス/コントラクトを破ることなくビジネス オブジェクトを変更できることを意味します。
他のヒント
ハイブリッドをやると思います。このようなオブジェクトを使用します
public class TransferObject
{
public string Type { get; set; }
public byte[] Data { get; set; }
}
それから、オブジェクトをシリアル化して圧縮する素敵な小さなユーティリティがあります。
public static class CompressedSerializer
{
/// <summary>
/// Decompresses the specified compressed data.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="compressedData">The compressed data.</param>
/// <returns></returns>
public static T Decompress<T>(byte[] compressedData) where T : class
{
T result = null;
using (MemoryStream memory = new MemoryStream())
{
memory.Write(compressedData, 0, compressedData.Length);
memory.Position = 0L;
using (GZipStream zip= new GZipStream(memory, CompressionMode.Decompress, true))
{
zip.Flush();
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
result = formatter.Deserialize(zip) as T;
}
}
return result;
}
/// <summary>
/// Compresses the specified data.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data">The data.</param>
/// <returns></returns>
public static byte[] Compress<T>(T data)
{
byte[] result = null;
using (MemoryStream memory = new MemoryStream())
{
using (GZipStream zip= new GZipStream(memory, CompressionMode.Compress, true))
{
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formatter.Serialize(zip, data);
}
result = memory.ToArray();
}
return result;
}
}
次に、型名を持つ転送オブジェクトを渡すだけです。したがって、次のようなことができます
[WebMethod]
public void ReceiveData(TransferObject data)
{
Type originType = Type.GetType(data.Type);
object item = CompressedSerializer.Decompress<object>(data.Data);
}
現時点では、圧縮シリアライザーはジェネリックスを使用して強く型指定されていますが、上記のoriginType を使用して逆シリアル化する Type オブジェクトを取り込むメソッドを簡単に作成できます。すべては実装に依存します。
これがあなたに何かアイデアを与えてくれることを願っています。ああ、もう 1 つの質問に答えると、wsdl.exe は型の再利用をサポートしていませんが、WCF はサポートしています。
ダレン 書きました:ハイブリッドをやると思います。このようなオブジェクトを使用します...
興味深いアイデア...(wsdl 化された) オブジェクト自体ではなく、オブジェクトのシリアル化されたバージョンを渡します。ある意味では、私はその優雅さが気に入っていますが、別の意味では、Web サービスを潜在的なサードパーティやパートナーなどに公開するという目的に反するように思えます。彼らは何を渡すべきかをどのようにして知るのでしょうか?純粋に文書に頼らなければならないのでしょうか?また、シリアル化は .Net に非常に固有であるため、「異種クライアント」の側面も一部失われます。批判するつもりはありませんが、あなたが提案しているものがこのようなタイプのユースケースも対象としているかどうか疑問に思っているだけです。ただし、密閉された環境で使用しても問題はないと思います。
WCFを調べてみようかな...ずっと避けてきたけど、もうその時が来たのかもしれない。
ああ、確かに、私がこれを行うのは、私が Web サービスのコンシューマーである場合、またはオブジェクトをリクエストする何らかのコントローラーがあり、Web サービスを直接消費するのではなくシリアル化と送信を処理する場合にのみです。しかし、実際には、Web サービスを直接使用している場合は、そもそもその型を含むアセンブリは必要ないか、必ずしも必要ではないため、wsdl が生成するオブジェクトを使用する必要があります。
そして、はい、私が提案したものは非常に .NET に特化しています。なぜなら、私は他のものを使いたくないからです。他に私が .net 以外の Web サービスを利用するのは JavaScript でしただけですが、今では XML Web サービスの応答ではなく JSON 応答のみを使用しています:)