1

以前は、インポートされたWSDL Web参照を使用していたC#プロジェクトでカスタムSOAPヘッダーを作成する必要がありました。私はそれを行う方法を見つけましたが、私はそれに満足することはなく、もっと良い方法があるかどうか疑問に思いました。私がしたことは、SoapHeaderから派生したヘッダーを作成することでした。

[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://model.test.net")]
[System.Xml.Serialization.XmlRootAttribute("securitytoken", Namespace = "http://model.test.net", IsNullable = false)]
public class SpecialHeader : SoapHeader
{ 
  [System.Xml.Serialization.XmlTextAttribute()]
  public string aheadervalue;
}

次に、WSDLから生成されたコードを変更し、カスタムヘッダーを含めたい各Web呼び出しの前に、新しいヘッダーのインスタンスと次のインスタンスに参照を追加する必要がありました。

[System.Web.Services.Protocols.SoapHeaderAttribute("instancename", Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut)]

ここで、「instancename」は、生成されたクラスのカスタムヘッダーのインスタンス変数名です。

これは正常に機能しますが、WSDLを変更すると、クラスが再生成されるため、すべてをやり直す必要があります。他の言語では、生成されたコードの外部にヘッダーを追加できるため、C#で行われる方法が欠落している可能性があります。これを行うためのより良い方法はありますか?

4

4 に答える 4

3

.Net2.0およびasmxWebサービスを使用しているようです。.Net 3.0にWCF(Windows Communication Framework)と呼ばれるフレームワークがあることをご存知ですか。新しいフレームワークに移行するのは簡単ではないことは知っていますが、WCFを使用すると多くのことができます。さらに、WCfは、Webサービス(リモーティング、msmqなど)以外にも使用できます。これは、Microsoftが将来に向けて賭けているフレームワークです。つまり。石鹸ヘッダーの操作は、MessageContractsを使用して行われます。

したがって、答えは、WCFではMessageContractsを使用してこれを実行できるということです。

于 2008-12-17T15:27:47.270 に答える
2

生成されたクラスは部分クラスであるためです。同じ名前空間とクラス名 (再び部分クラス) を持つ別のファイルで定義できます。次に、その仮想メソッドをオーバーライドして、一度定義できます。

これにより、再生成されたクラスをさらに変更しても、作成したクラスには影響しません。

新しいクラス ファイルでは、"GetWriterForMessage" を使用してオーバーライドし、新しい SOAP ヘッダーを追加できます。

public partial class SampleService
{
    public string MessageID { get; set; }

    protected override System.Xml.XmlWriter GetWriterForMessage(System.Web.Services.Protocols.SoapClientMessage message, int bufferSize)
    {
        message.Headers.Add(new UsernameSoapHeader("Username"));
        message.Headers.Add(new PasswordSoapHeader("Password"));
        message.Headers.Add(new MessageIDSoapHeader(MessageID));
        return base.GetWriterForMessage(message, bufferSize);
    }
}
于 2011-06-30T07:54:05.070 に答える
1

それを行う方法があります。これは必ずしもきれいであるとは限りません。また、非常に単純な Web サービスでは、努力する価値がないかもしれませんが、少なくとも、コードを再生成するときに属性を再度追加する必要がなくなります。

ジェネレーターは部分クラスを生成するため、次のことができます。

  1. 別の「部分」セクションで Web サービス クラス (SoapHttpClientProtocol から派生したもの) を拡張するファイルをプロジェクトに追加します (つまり、生成されたクラスと同じ名前空間と名前を使用し、それを「部分」とマークします)。

  2. ヘッダーを追加したいメソッド (つまり、すでに属性を追加しているメソッド) を生成されたコードからコピーし、拡張セクションに貼り付けます。

  3. 生成されたコード内のメソッドと競合しないようにメソッドの名前を少し変更し、一致するように Invoke に渡される名前を変更します。(メソッドの他の属性も微調整して、それらが WSDL の適切な呼び出しに引き続きマップされるようにする必要がある場合があります。)

  4. 名前を変更したメソッドにカスタム ヘッダー属性を追加し、拡張セクションにもヘッダー インスタンス フィールドを追加します。

  5. 元のバージョンではなく、名前を変更したバージョンをコードから呼び出します。

メソッド シグネチャが WSDL で変更されない限り、再生成してもコードを変更する必要はありません。(比較的短いメソッド実装のみをコピーするため、WSDL からの他の構造は生成されたコードから引き続き出てきます。したがって、それらが変更された場合、再生成時に更新されたバージョンが自動的に取得されます。確かに、WSDL がそうでない場合他の構造を持っている場合、これの有用性はおそらくいくらか制限されます。)

それはまだ理想的ではありませんが、未加工の XML メッセージをインターセプトしてヘッダーを直接挿入しようとすることを除いて (これはおそらく実行できますが、厄介なことになるでしょう)、私が知っている他のオプションは実際にはありません (移動せずに)とにかくWCFに)。

于 2008-12-02T04:44:44.940 に答える
0

今日、この問題に遭遇しました。自動生成されたクラスから派生するクラスの作成を終了し、GetWriterForMessageメソッドをオーバーライドして、ヘッダーが常に存在するようにしました。メソッドを呼び出すたびにヘッダー値を更新します。

于 2010-04-13T16:40:25.323 に答える