2017-01-17 22 views
2

Webクライアントで別のサーバーに接続するために使用できるWeb API 2のメソッドの一般的なセットを作成する方法を探しています。Web Api 2複数のパラメータを持つ一般的なパススルーメソッド

まず、自分のインフラストラクチャについて説明します。私の会社で一般的に採用されている簡略化されたセットアップ(データベースサーバーなどを除く)は、2つのメインサーバーで構成されています。アプリケーションとサイトをホストするために使用されるWebレイヤーサーバーと、サービス/アプリケーションなどを含むアプリケーションレイヤーサーバーがあります。

ハウスルールは、Webサーバー上のアプリケーションがアプリケーション上のもの最初にプロキシまたはブローカサービスを経由せずに

この問題に対する私の現在の解決策は、api内のすべてのルートのコピーを含むSDK Web APIサービスを作成することです。アプリケーション(この場合はアングルアプリ)はREST APIコールを介してこのSDKサービスを呼び出します。この中間サービスの仕事は.NET HttpClientを使用してこの呼び出しを「実際の」APIサービスへの呼び出しに変換することです他のサーバー。

これは素晴らしいことですが、これまでのところ問題はありませんでしたが、このようなことをする良い方法があると感じています。私はこの種のことを記述する記事をオンラインで検索したが、短くなってしまった。私は.NETやWeb APIを使用する専門家ではない。

今私が持っている解決策の例を挙げておきます。私のデータベースに現在保存されているすべてのクライアントを取得する呼び出しです。

public class ClientsController: ApiController 
{ 
    // http client used to translate calls to api service 
    private HttpClient httpClient = new HttpClient() 
    { 
     BaseAddress = new Uri(ConfigurationManager.AppSettings["apiUrl"]) 
    }; 

    [Route("clients")] 
    [HttpGet] 
    public IHttpActionResult GetClients() 
    { 
     httpClient.DefaultRequestHeaders.Accept.Clear(); 
     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"); 

     List<Client> clients = null; 

     try 
     { 
      HttpResponseMessage result = httpClient.GetAsync("clients").Result; 

      if (result.IsSuccessStatusCode) 
      { 
       clients = result.Content.ReadAsAsync<List<Client>>().Result; 
       return Content(result.StatusCode, clients); 
      } 

      // return the failed reason code 
      return Content(result.StatusCode, result.ReasonPhrase); 
     } 
     catch (Exception e) 
     { 
      return Content(HttpStatusCode.InternalServerError, e.Message); 
     } 
    } 
} 

このルートは、他のサーバー上で実行されている私のAPIサービスに実装され、データベースからクライアントを取得し、その後、私のアプリケーションに表示されるように戻るに戻って、このサービスへのクライアントのリストを返します。画面上。

api内のすべてのルートに対して、1組のメソッド(上に示したものと実際の実装)が存在します。

理想的には、各HTTP動詞に1つのメソッドを含めることができます。そこには渡されるルートがあり、apiサービスからそのルートが呼び出され、アイテムまたは結果コードの戻り値を処理します。それを2つの場所に追加することなく、新しいエンドポイントのセットをAPIに追加することができる点を除けば、現在の機能と似ています。

これは私が立ち往生した場所です。どのようにこれを行うことができたか、私が探検しなかった可能性があるいずれかの洞察は素晴らしいでしょう。

この長い質問をお読みいただきありがとうございます。

+0

2つのWeb APIサーバーがあり、そのうちの1つは実サーバーで、もう1つは着信要求を実際のサーバーにリダイレクトする厳しい仲介者ですか?あれは正しいですか ? – Vladimir

+0

@Vladimir yep thats right – peppermcknight

答えて

1

後期応答は、私はに戻って、より緊急の何かのためにプロジェクトをオフに引っ張られていましたこれをオフにして、私のために働く解決策を得ることができました。だから私は誰にも助けになるようにここに投稿すると思っていました。

私のパススルーサービスは「SDK」と見なされ、SDKと他のサービスとの間のエンドポイントを完全に制御しています。これを「API」と呼びます。

public class SdkController : ApiController 
{ 

    private HttpClient httpClient = new HttpClient() 
    { 
     BaseAddress = new Uri(ConfigurationManager.AppSettings["apiUrl"]) 
    }; 

    [HttpGet, HttpPost, HttpPut, HttpDelete, Route("v2/{*url}")] 
    public HttpResponseMessage PerformRequest(string url) 
    { 
     httpClient.DefaultRequestHeaders.Accept.Clear(); 
     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

     try 
     { 
      HttpResponseMessage response = null; 
      HttpContent requestBody = null; 
      string requestUrl = Request.RequestUri.LocalPath.Replace("/SDK/v2/", ""); 
      string requestMethod = Request.Method.ToString(); 

      switch (requestMethod) 
      { 
       case "GET": 
        response = httpClient.GetAsync(requestUrl).Result; 
        break; 
       case "POST": 
        requestBody = Request.Content; 
        response = httpClient.PostAsync(requestUrl, requestBody).Result; 
        break; 
       case "PUT": 
        requestBody = Request.Content; 
        response = httpClient.PutAsync(requestUrl, requestBody).Result; 
        break; 
       case "DELETE": 
        response = httpClient.DeleteAsync(requestUrl).Result; 
        break; 
      } 

      return response; 
     } 
     catch 
     { 
      return new HttpResponseMessage() 
      { 
       StatusCode = HttpStatusCode.InternalServerError, 
       ReasonPhrase = "Internal Server Error" 
      }; 
     } 
    } 

} 

SDKのすべての私のエンドポイントの要求が共通の「V2 /」プレフィックスを持っている、と私は要求が起こったりされ、このパススルー方式の内部で気にする必要はありませんので、私はこれを行うことができましたどのリクエストが返ってきているか、送信しているか - これに対処するためのすべてのロジックは、より大規模なAPIサービスの中にあります。

ここではあまりうまくいかないものは、私のエラー処理ですが、私のAPIから返される可能性のあるエラーをより正確に投影するよう修正しています。

1

ASP.NETモジュール(IHttpModuleを実装)を使用できます。このようにして、あなたが好きなようにリクエスト/レスポンスを読んで変更することができます。

考えてみましょう:何年か前に、受け取ったリクエストを複数のリスナーにブロードキャストするモジュールを書きました。リスナの1つがレスポンスを処理します(または定義されていない場合、モジュールは200 OKで応答します)。受け取ったURLパラメータまたはオブジェクトは、リスナに渡すのが簡単です。

処理は簡単です。リクエストをすべてのリスナーに渡しますが、ハンドラ(定義されている場合)を除いてレスポンスを無視します(fire-and-forget)。応答が受信されると、これをモジュールの応答として渡します。時間がかかる場合は、自動的にタイムアウトになります。

構成では、プロトコル、動詞、およびリスナーが応答を処理する必要があるかどうかを含めて(複数の)他のルートにマップされたすべての受け入れられたルートが記述されています。つまり、https POSTをhttp GET + urlパラメータに変換することもできます。

注目のポイントはセキュリティです。受け取ったものだけを渡すことは安全ではないかもしれません。また、私はデータベースにプロキシを接続しません。送信する前に、いくつかのチェックとサニタイズを行うことができます。

ヘッダーも送信する必要があるかもしれません。たとえば、トークンが送信された場合などです。

私はこれがあなたにアイデアを与えることを望みます。そこインターネット上で見つけるための十分な情報があるが、ここではいくつかのリンクです:この質問へ

HttpModule Change Response

Custom HttpModule Example

関連する問題