リフレクションを使用して ASP.NET Web サービスを呼び出す
-
09-06-2019 - |
質問
ASMX Web サービス MyService があるとします。このサービスには MyMethod というメソッドがあります。次のようにサーバー側で MyMethod を実行できます。
MyService service = new MyService();
service.MyMethod();
実行時まで不明なサービスとメソッドを使用して、同様のことを行う必要があります。
反省することがそのための方法だと思います。残念ながら、それを機能させるのに苦労しています。このコードを実行すると:
Type.GetType("MyService", true);
次のエラーがスローされます。
アセンブリ 'App_Web__ktsp_r0、Version=0.0.0.0、Culture=neutral、PublicKeyToken=null' からタイプ 'MyService' を読み込むことができませんでした。
ご指導いただければ幸いです。
解決
これが最善の方法かどうかはわかりません。私にとって最も明白な方法は、HTTP リクエストを作成し、実際の HTTP GET または POST を使用して Web サービスを呼び出すことです。あなたの方法を使用すると、Web サービスに送信するデータをどのように設定するか完全にはわかりません。VB.Netにサンプルコードを追加しました。
Dim HTTPRequest As HttpWebRequest
Dim HTTPResponse As HttpWebResponse
Dim ResponseReader As StreamReader
Dim URL AS String
Dim ResponseText As String
URL = "http://www.example.com/MyWebSerivce/MyMethod?arg1=A&arg2=B"
HTTPRequest = HttpWebRequest.Create(URL)
HTTPRequest.Method = "GET"
HTTPResponse = HTTPRequest.GetResponse()
ResponseReader = New StreamReader(HTTPResponse.GetResponseStream())
ResponseText = ResponseReader.ReadToEnd()
他のヒント
// これを試してください ->
Type t = System.Web.Compilation.BuildManager.GetType("MyServiceClass", true);
object act = Activator.CreateInstance(t);
object o = t.GetMethod("hello").Invoke(act, null);
Reflection がそこで機能しない理由はわかりませんが、コンパイラがあなたのクラスから新しいクラスを作成しているのではないかと思います。 [WebService]
注釈)、問題を解決する可能性のあるアドバイスをいくつか示します。
つまり、WebService は単純かつ浅くしてください。ファサードパターンの実装.
サービスで計算を実装クラスに委任します。実装クラスはリフレクションを通じて簡単に呼び出すことができます。このように、WebService クラスはシステムの単なるフロントになります。ロジックは WebService ではなく実際のビジネス層オブジェクトに結合されるため、電子メール ハンドラーや XML-RPC フロントエンドなどを追加することもできます。
WebService クラスをアーキテクチャ内の UI レイヤー オブジェクトとして考えてください。
これは、誰かがおそらく拡張できる簡単な答えです。
WSDL テンプレート アプリ (WSDL.exe) を使用してサービス ラッパーを生成すると、SoapHttpClientProtocol 型のクラスが構築されます。手動で行うこともできます。
public class MyService : SoapHttpClientProtocol
{
public MyService(string url)
{
this.Url = url;
// plus set credentials, etc.
}
[SoapDocumentMethod("{service url}", RequestNamespace="{namespace}", ResponseNamespace="{namespace}", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public int MyMethod(string arg1)
{
object[] results = this.Invoke("MyMethod", new object[] { arg1 });
return ((int)(results[0]));
}
}
このコードはテストしていませんが、WSDL ツールを実行しなくてもスタンドアロンで動作すると思います。
私が提供したコードは、リモート呼び出しを介して Web サービスに接続する呼び出し側コードです (たとえ何らかの理由で実際にリモートにしたくない場合でも)。Invoke メソッドは、それをソープコール。@Dave Ward のコードは、実際にクラスを参照できる限り、HTTP 経由で Web サービス呼び出しをバイパスしたい場合には正しいです。おそらく、内部タイプは "MyService" ではありません。確実に知るには、コントロールのコードを検査する必要があります。
@キビー:HTTP パフォーマンスの低下を避ける必要があります。これはリモート呼び出しではないため、オーバーヘッドがすべて追加されます すべき 不要であること。
@ダレン:私はその設計哲学に間違いなく同意します。ここでの問題は、私がサービスやその基盤となるビジネス ロジックを制御できないことです。
これがためのものです サーバーコントロール これは、Web サービス自体の実装方法とは直交して、任意のサービス/メソッドに対して実行する必要があります。
あなたの投稿からはわかりませんが、
留意すべき点の 1 つは、リフレクションを使用する場合は、自動生成された Web サービス クラス (Web サービスの WSDL から作成されたもの) のインスタンスを作成する必要があるということです。サービスのサーバー側を担当するクラスは作成しないでください。
Webサービスがある場合
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class WebService1 : System.Web.Services.WebService
{
...
}
クライアントでそのアセンブリを参照して次のようなことを行うことはできません。
WebService1 ws = new WebService1 ();
ws.SomeMethod();
@ラドゥ:インスタンスを作成して、そのようにメソッドを呼び出すことができます。たとえば、この ASMX があるとします。
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ScriptService] public class MyService : System.Web.Services.WebService { [WebMethod] public string HelloWorld() { return "Hello World"; } }
次のように ASPX ページの分離コードから呼び出すことができます。
MyService service = new MyService(); Response.Write(service.HelloWorld());
それは機能しないはずだと言いたいのですか?
この質問を振り返ってみましたが、あなたが直面しているのは、ASMX コードがサイトの動的コンパイルの一部としてランダムな名前の DLL に組み込まれるということだと思います。型を検索するコードは、デフォルトでは、独自のアセンブリ (受け取ったエラーから判断すると、別の App_Code DLL) とコア ライブラリのみを検索します。GetType() に特定のアセンブリ参照「TypeName, AssemblyName」を指定することもできますが、自動生成されたアセンブリの場合は、再コンパイルのたびに新しい名前が付けられるため、これは不可能です。
解決....私はこれまでにこれを行ったことがありませんが、次のようなものを使用できるはずだと思います。
System.Web.Compilation.BuildManager.GetType("MyService", true)
BuildManager は作成した DLL を認識しており、どこを調べればよいかを知っているためです。
これは実際には Web サービスとは関係ないと思いますが、独自のコードであれば、ファサード パターンについては Daren の言う通りです。