動的な C#.NET Web サービス
-
06-09-2019 - |
質問
C# ASP.NET プロジェクトのクラスを使用して、ランダムなスクリプト言語で書かれたスクリプトが Web サービス メソッドを動的に公開できるようにしています。つまり、スクリプトは、任意の署名を持つ任意の名前のメソッドを公開できる必要があります (ただし、とにかく有効なので)この SOAP インターフェイスを介して外部に接続する(ハードコードの変更を必要とせずに、自由に追加および削除できます)ため、C# で Web サービス クラスを作成できる必要があります。実行時にメソッドを動的に追加および削除します。
これまで思いついた最善の計画は、(実行時に) Web サービスを表す C# コードを生成し、System.Reflection.Emit を使用してそれをコンパイルし、実行時にアセンブリを読み込むことです。すべて、スクリプトが追加するたびに実行されます。または、サービスとの間でメソッドを削除します (頻繁に発生するべきではありませんが、注意してください)。
これより良いアイデアを持っている人はいますか?
解決
あなたは SoapExtensionReflector <使用してWSDLを変更することができます/>クラス。 カーク・エヴァンスブログのから:
あなたのタイプがあなたのサービスのWSDL定義を提供するために、オーバー反映されているときにSoapExtensionReflectorが呼び出されます。あなたは、反射呼び出しをインターセプトし、WSDL出力を変更するには、このタイプを活用することができます。
次の例では、2 Webサービスメソッドのうちの最初の方法を削除します:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public int Multiply(int a, int b)
{
return a * b;
}
}
SoapExtensionReflectorから継承したクラスを作成します:
namespace TestWebservice
{
public class MyReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
//no-op
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
if (description.PortTypes[0].Operations.Count == 2)
description.PortTypes[0].Operations.RemoveAt(0);
if (description.Messages.Count == 4)
{
description.Messages.RemoveAt(0);
description.Messages.RemoveAt(0);
}
foreach (Binding binding in description.Bindings)
{
if (binding.Operations.Count == 2)
binding.Operations.RemoveAt(0);
}
if (description.Types.Schemas[0].Items.Count == 4)
{
description.Types.Schemas[0].Items.RemoveAt(0);
description.Types.Schemas[0].Items.RemoveAt(0);
}
}
}
}
web.configファイル内の設定/ system.webセクションにこれを追加します。
<webServices>
<soapExtensionReflectorTypes>
<add type="TestWebservice.MyReflector, TestWebservice" />
</soapExtensionReflectorTypes>
</webServices>
これは、動的にWSDLドキュメントからメソッドを削除するためにあなたの出発点を与える必要があります。また、それが無効になっている場合、ウェブメソッドからNotImplementedExceptionをスローする必要があります。
最後に、あなたはなし?WSDLパラメータの.asmxエンドポイントを呼び出すことによって生成するWebサービスのドキュメントを無効にする必要があります。いくつかのURLにwsdlHelpGenerator要素のhref属性を設定します。あなたはあなた自身のドキュメントハンドラのための出発点としてDefaultWsdlHelpGenerator.aspxを使用することができます。 XMLファイル、2002年8月の中のWebサービスマニュアルの質問を参照してください。
他のヒント
XMLRPCは、それは、かなり死んでいないですね。
SOAPはWSDLを意味します。どのように動的にWSDLを生成していますか?
あなたは、WCFを使用してになります。私はあなたがWSDL(および他のメタデータ)を生成するプロセスの制御を取ることができるでしょう期待して、まだあなたはまた、受信メッセージの処理の制御を取ることができるはずです。特に、あなたはなど、どのようなパラメータを渡すために、実行するスクリプトを決定するために、着信メッセージを調べることができるようになります。
あなたはxs:any
の入力と出力タイプでWCFサービスを作成し、生Message
として着信要求を処理することができます。それはあなたがあらゆるタイプのデータを受け入れ、任意のタイプのデータを返すことができるようになります。あなたは、データコントラクトまたは静的なタイプだけでMessage
とMessage
アウトを使用することはありません。
このアプローチの問題は、WSDLからプロキシを生成することは本当にメソッドを呼び出すためのラッパーを提供以外の消費者を助けるために何もしないということです。それは難しいことではありませんなど、手圧延のデータ型を必要とする方法、に受け入れられるデータを提供する、それは難しい、入力された契約と同じように直感的ではありません。
これは、SOAPインターフェイスでなければなりませんか?それは、ルート/ RESTの/ etcベースのAPIへのより適切かもしれないようにそれは聞こえます。あなたは、実際に、私は<のhref = "http://code.googleのために非常によく似た何かに取り組んでいる(かなり簡単に(メソッドにアクションを解決するカスタムIController.Execute
法による)ASP.NET MVCで何かを行うことができます.COM / P /いるProtobufネット/ソース/閲覧/トランク/デモ-RPCサーバ-MVC /ヘルパー/ ProtoController.cs」relが= "nofollowをnoreferrer">現時点では私自身のコードの一部)。
たとえば、あなたがルートを持っているかもしれません。
http://myserver/myservice/mymethod
これは(身体または引数のいずれか)のペイロード(パラメータ)を受け入れ、それに応答して結果を返します。非MVCでは、ワイルドカードマッピングされたジェネリックハンドラと似た何かを行うことができるはずます。
ここに提案があります:
- WCF を使用します。
次のブログ投稿で情報を使用して、WCFからWSDLを作成します。
http://www.pluralsight.com/community/blogs/karillg/archive/2006/06/18/28380.aspx
その後、MEXを使用してこの情報を公開できます。
サービスは、クライアントがメタデータをダウンロードしてサービスを呼び出すためにオープンします。