PCLライブラリでのIfModifiedSince HTTPヘッダーの安全な使用

突然接続が失われました 複数のプラットフォーム用のアプリケーションを開発しています。PCLを使用してプラットフォームに依存しない部分全体を作成し、コンポーネントの最大限の再利用を実現しようとしています。 サーバーとの通信には、HttpWebRequestクラスが使用され、トランスポートレベルで必要なすべての機能が実装されます。



最近、プロトコルが最適化され、関連の地平線を示す送信データ量を削減することが可能になりました。 この最適化は、IfModifiedSince HTTPヘッダーの処理を使用して実装されていますが、IfModifiedSinceプロパティはPCLのHttpWebRequestオブジェクトでは使用できません。 これは問題ではないようでしたが、ヘッダーはリクエストヘッダーコレクションに直接追加されました。



request.Headers[HttpRequestHeader.IfModifiedSince] = timeStamp.ToString();
      
      





WindowsPhoneアプリケーションでソリューションをテストした結果、そのパフォーマンスは確信しましたが、トランスポートレベルのすべてのユニットテストでエラーが発生しました。 この問題を調査した結果、WindowsプラットフォームのWebHeaderCollection実装ではこのヘッダーを直接設定できず、開発者はHttpWebRequest.IfModifiedSinceプロパティを使用する必要があることがわかりました。これはPCLアセンブリでは使用できません。



これを解決するために、次のロジックを実装するHttpWebRequestクラスの拡張メソッドを作成しました。



メソッドの最初の呼び出しで、リクエストヘッダーのコレクションにヘッダーを追加しようとします。失敗した場合、リフレクションを使用して、リクエストオブジェクトのIfModifiedSinceフィールドを探し、デリゲートを作成してキャッシュしてプロパティ値を設定します。



メソッドへの後続の呼び出しで、キャッシュされたデリゲートを使用して、IfModifiedSinceヘッダーの値を設定します。



 namespace System.Net { public static class NetExtensions { private static Action<HttpWebRequest, DateTime> _setIfMofifiedSince; public static void SetIfModifiedSince(this HttpWebRequest request, DateTime value) { Guard.NotNull(request); if (_setIfMofifiedSince != null) { _setIfMofifiedSince(request, value); return; } try { request.Headers[HttpRequestHeader.IfModifiedSince] = value.ToString(); return; } // ReSharper disable once EmptyGeneralCatchClause catch { } var property = request.GetType().GetRuntimeProperty("IfModifiedSince"); if (property != null && property.CanWrite) { var method = property.SetMethod; if (method != null) { _setIfMofifiedSince = (Action<HttpWebRequest, DateTime>)method.CreateDelegate(typeof(Action<HttpWebRequest, DateTime>)); } } if (_setIfMofifiedSince == null) { throw new Exception("Unable to set IfModifiedSince"); } _setIfMofifiedSince(request, value); } } }
      
      







この拡張メソッドを使用すると、コードは読みやすく理解しやすいままです。



 request.SetIfModifiedSince(timeStamp);
      
      






All Articles