2016-02-25 17 views
12

エンコードされたすべてのリクエストをデコードするHTTPモジュールがあります。 これは、すべてのWCF要求に素晴らしい作品が、ませウェブのAPI requests-でWeb APIの要求を(両方のPOSTとGET)サービスになるには、まだ私はそれが再び、HTTPモジュールをヒットが、ことがわかりウェブAPIとHTTPモジュール

をエンコードそれでもコード化されたサービスに到達します。 どうすれば修正できますか?私は間違って何をしていますか? Web ApiのMessage Handlersで動作する方が良いとわかっていますが、HTTPモジュールはあまりにもうまく動作しないと思いますか?

HTTPモジュール:

public void Init(HttpApplication context) 
    { 
     context.BeginRequest += new EventHandler(context_BeginRequest); 
     context.EndRequest += context_PreSendRequestContent; 
    } 

    void context_PreSendRequestContent(object sender, EventArgs e) 
    { 
     string encodedQuerystring = HttpContext.Current.Request.QueryString.ToString(); 
     if (!string.IsNullOrEmpty(encodedQuerystring)) 
     { 
      System.Collections.Specialized.NameValueCollection col = new System.Collections.Specialized.NameValueCollection(); 
      col.Add("q", encodedQuerystring); 
      WebFunction.CreateQuerystring(HttpContext.Current, col); 
     } 


    } 

    void context_BeginRequest(object sender, EventArgs e) 
    { 
     string encodedQueryString = String.Empty; 
     if (HttpContext.Current.Request.QueryString.Count > 0 && HttpContext.Current.Request.QueryString["q"] != null) 
     { 

      object _p = HttpContext.Current.Request.QueryString; 
      encodedQueryString = HttpContext.Current.Server.UrlDecode(HttpContext.Current.Request.QueryString["q"].ToString()); 

      string originalQueryString = HttpContext.Current.Server.UrlDecode(WebFunction.Base64Decode(encodedQueryString)); 

      if (!string.IsNullOrEmpty(originalQueryString)) 
      { 
       WebFunction.CreateQuerystring(HttpContext.Current, WebFunction.ConvertQueryToCollection(originalQueryString)); 

      } 
     } 
    } 

WebFunction:

public static void CreateQuerystring(HttpContext context, System.Collections.Specialized.NameValueCollection nameValueCollection) 
    { 
     // reflect to readonly property 
      PropertyInfo isreadonly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); 
      // make collection editable 
      isreadonly.SetValue(context.Request.QueryString, false, null); 
      context.Request.QueryString.Clear(); 
      context.Request.QueryString.Add(nameValueCollection);   
      // make collection readonly again 
      isreadonly.SetValue(context.Request.QueryString, true, null);    
    } 

Web APIを:

public class NamesController : ApiController 
{ 
    [HttpGet] 
    [ActionName("GET_NAMES")] 
    public Drugs_ResponseData Get(string q) 
    { 
//need to add the decode function to get it to work 
     string[] arrAmpersant = Commonnn.DecodeFrom64(q).Split('&'); 

     Names_obj = new Names(); 
     return _obj.GetResult(Convert.ToInt32(Commonnn.GetValFromEqual(arrAmpersant[0]))); 
    } 
} 
+0

httpモジュールはどこに登録しましたか? ''内に登録した場合、アプリケーションプールは統合モードで実行する必要があります。 –

+0

@KhanhTOはにあり、統合モードで実行されます。それはHTTPモジュールに到達しますが、依然としてリクエストにエンコードされます。 – DasDas

+0

リクエストごとにエンコードされたクエリ文字列が使用されている場所の数と、1時間にページにアクセスした訪問者の数を確認できますか? – LGSon

答えて

2

Web APIはリクエスト内でQueryStringコレクションを使用していないようですが、URL自体を解析しているようです。

GetQueryNameValuePairsの方法をthis fileに表示します。これらはUriを使用して、そのQueryプロパティを解析します。

だから、あなたがそれを行うには、2つのオプションがあります。

  1. を汚れ一つは、あなたのHTTPモジュールに要求のURIを変更することです。私はそれが可能かどうか分からないが、いくつかの反省はそのトリックを行うことができる。
  2. Web APIメッセージハンドラを使用するほうが良い方法です。
+0

エンコードされた本体のPOSTが私のアプリケーションのDelegatingHandlersを通じて配信されないようにする、IISのデフォルト要求パイプラインに構造的なものがあるかどうか知っていますか? –

2

Context.Itemsを使用し、QueryStringにエンコードされたバージョンがあるようにすることをお勧めします。

それは非常によくあなたが簡単に任意のオブジェクトを格納し、モジュール間で共有する要求を通じて最後のキー/値の辞書に組み込まれて知られていない、ハンドラなど

これを使用すると、非常にのようにあなたを与えるだろうQueryStringオブジェクトのロックを解除するよりもパフォーマンスが優れていますが、さらに重要なのは、値を1か所で処理して多くのもので再利用し、必要に応じて、2番目の値、完全なQueryStringコレクションまたは要求。

void context_BeginRequest(object sender, EventArgs e) 
{ 
    string encodedQueryString = String.Empty; 
    if (HttpContext.Current.Request.QueryString.Count > 0 && HttpContext.Current.Request.QueryString["q"] != null) 
    { 

     string encodedQueryString = HttpContext.Current.Server.UrlDecode(HttpContext.Current.Request.QueryString["q"].ToString()); 

     HttpContext.Current.Items("qs_d") = HttpContext.Current.Server.UrlDecode(WebFunction.Base64Decode(encodedQueryString)); 

    } 
} 

Web APIを:

public class NamesController : ApiController 
{ 
    [HttpGet] 
    [ActionName("GET_NAMES")] 
    public Drugs_ResponseData Get(string q) 
    { 
    string[] arrAmpersant = Commonnn.DecodeFrom64(HttpContext.Current.Items("qs_d").ToString()).Split('&'); 

    Names_obj = new Names(); 
    return _obj.GetResult(Convert.ToInt32(Commonnn.GetValFromEqual(arrAmpersant[0]))); 
    } 
} 

サイドノート:私はあなたが二回HttpContext.Current.Server.UrlDecodeを呼び出す参照してください。私はあなたのBase64Decodeメソッドが再び値をエンコードしない限り、あなたが必要とは思わない。

1

あなたはそれが可能である。この

protected void Application_BeginRequest(object sender, EventArgs e) 
     { 
      var app = (HttpApplication)sender; 
      string path = app.Context.Request.Url.PathAndQuery; 
      int pos = path.IndexOf("?"); 
      if (pos > -1) 
      { 
       string[] array = path.Split('?'); 
       app.Context.RewritePath(array[0]+"?"+ HttpContext.Current.Server.UrlDecode(array[1])); 
      } 
     } 
0

のように扱うことができますが、ここでは、リスクを存在することを意味するもの、反射が必要になります。私がソリューションの後にもっとクリーンなソリューションであると考えているものをお勧めします。

if (!string.IsNullOrEmpty(originalQueryString)) 
{ 
    var request = HttpContext.Current.Request; 
    request.GetType().InvokeMember("QueryStringText", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, request, new[] { "q=" + originalQueryString }); 
    //WebFunction.CreateQuerystring(HttpContext.Current, WebFunction.ConvertQueryToCollection(originalQueryString)); 
} 

ソリューションこのはリクエストの次のプロパティを更新します。

Request.Param 
Request.QueryString 
Request.ServerVariables 
Request.Url 

しかし更新されません。

Request.RawUrl 

クリーナーソリューション

IIS URL書き換えモジュールトマーシュヘルツェグの答え@上への追加
http://www.iis.net/learn/extensions/url-rewrite-module/developing-a-custom-rewrite-provider-for-url-rewrite-module

+0

これは興味深いアプローチのように見えましたが、試したときに新しいクエリ文字列がまだエンコードされていますか? ... OPがデコードされたクエリ文字列を探しているので、ここで何かが恋しいと思っていますか? – LGSon

+0

私のステップは次のとおりです。1 - WebAPIソリューションを作成しました。 2 - que queryString "q"を取得し、デコードし、ここに投稿したコードを実行するモジュールを作成しました。 3 - 文字列パラメータqを受け取って返すように作成されたValuesControllerを修正しました。モジュールを登録する前に、apiはエンコードされた文字列を返します。その後、返された文字列はデコードされます。 –

1

、私はむしろのWeb APIを対応するために、あなたのHttpModuleをを修正するよりも、Web APIをメッセージハンドラを実装します。

public class DecodeQueryStringMessageHandler : DelegatingHandler 
    { 
     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 
      CancellationToken cancellationToken) 
     { 
      if (request.Method == HttpMethod.Get) 
      { 
       var originalQueryString = request.RequestUri.Query; 
       if (!string.IsNullOrEmpty(originalQueryString)) 
       { 
        var ub = new UriBuilder(request.RequestUri) { Query = HttpUtility.UrlDecode(originalQueryString) }; 
        request.RequestUri = ub.Uri; 
       } 
      } 

      return base.SendAsync(request, cancellationToken); 
     } 
    } 
関連する問題