1

「if-modified-since」ヘッダーを WCF Web サービスで動作させようとしています。

ユーザーが私のサービスにリクエストを送信すると、次のように、リクエストのタイムスタンプを含む送信応答に ETag を追加します。

var tag = String.Format("\"{0:o}\"", new DateTimeOffset(DateTime.Now));

これにより、次の ETag ヘッダーが生成されます。

ETag: "2011-10-27T13:09:39.6242263-04:00"

次に、この値を取得し、次のような後続のリクエストの if-modified-since ヘッダーとしてエコー バックします。

If-Modified-Since:2011-10-27T13:09:39.6242263-04:00

WebOperationContext.Current.Headers.IfModifiedSince を調べると、提供された値が得られません。値は「12/31/1969 7:00:00 PM」固定です。

私は何を間違っていますか?

アップデート

Fiddler を使用すると、If-Modified-Since ヘッダーに任意の値を設定しても、コードで同じ 1969 値を取得できることを付け加えておきます。

4

1 に答える 1

2

まずIf-Modified-Since、リソースの最終変更時刻に関する条件ETag付き GET と、リソースの識別子に関する条件付き GET についてですので、2 つの概念を混在させる場合は注意してください。

WCF サービスで If-Modified-Since のサポートを実装する正しい方法は、オブジェクトで値CheckConditionalRetrieveを渡すことです。これについては、以下のコードを参照してください。IMS ヘッダーの値が に渡す日付より前の場合、メソッドはその時点で終了し、304 (Not Modified) 応答を返します。そうでなければ、それはただ続くでしょう。以下のコードはそれを示しています。DateTimeWebOperationContext.Current.IncomingRequestCheckConditionalRetrieve

別の問題: 使用している日付形式 (ISO 8601) でも機能しますが、仕様に基づいて正しくありません ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.htmlのセクション 14.25 、およびhttp://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1のセクション 3.3.1 を参照)、将来の問題を防ぐために有効な形式の使用を検討する必要があります。

http://blogs.msdn.com/b/endpoint/archive/2010/02/25/conditional-get-and-etag-support-in-wcf-webhttpで、WCF での条件付き GET サポートに関する適切な投稿を見つけることができます。-services.aspx .

public class StackOverflow_7919718
{
    [ServiceContract]
    public class Service
    {
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        public string GetData()
        {
            Console.WriteLine("If-Modified-Since header (1): {0}", WebOperationContext.Current.IncomingRequest.IfModifiedSince);
            WebOperationContext.Current.IncomingRequest.CheckConditionalRetrieve(DateTime.UtcNow);
            return "Data";
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        Console.WriteLine("Not sending If-Modified-Since header (should return 200):");
        Util.SendRequest(baseAddress + "/GetData", "GET", null, null);

        Console.WriteLine("Sending data in the past, ISO 8601 format (should return 200):");
        Util.SendRequest(baseAddress + "/GetData", "GET", null, null,
            new Dictionary<string, string> { { "If-Modified-Since", "2011-10-25T13:09:39.6242263-04:00" } });

        Console.WriteLine("Sending data in the future, ISO 8601 format (should return 304):");
        Util.SendRequest(baseAddress + "/GetData", "GET", null, null,
            new Dictionary<string, string> { { "If-Modified-Since", "2021-10-25T13:09:39.6242263-04:00" } });

        Console.WriteLine("Sending data in the past, RFC 1123 format (should return 200):");
        Util.SendRequest(baseAddress + "/GetData", "GET", null, null,
            new Dictionary<string, string> { { "If-Modified-Since", "Wed, 26 Oct 2011 01:00:00 GMT" } });

        Console.WriteLine("Sending data in the future, RFC 1123 format (should return 304):");
        Util.SendRequest(baseAddress + "/GetData", "GET", null, null,
            new Dictionary<string, string> { { "If-Modified-Since", "Mon, 27 Oct 2031 10:00:00 GMT" } });

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
public static class Util
{
    public static string SendRequest(string uri, string method, string contentType, string body)
    {
        return SendRequest(uri, method, contentType, body, null);
    }
    public static string SendRequest(string uri, string method, string contentType, string body, Dictionary<string, string> headers)
    {
        string responseBody = null;

        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
        req.Method = method;
        if (headers != null)
        {
            foreach (string headerName in headers.Keys)
            {
                switch (headerName)
                {
                    case "If-Modified-Since":
                        req.IfModifiedSince = DateTime.Parse(headers[headerName]);
                        break;
                    default:
                        req.Headers[headerName] = headers[headerName];
                        break;
                }
            }
        }
        if (!String.IsNullOrEmpty(contentType))
        {
            req.ContentType = contentType;
        }

        if (body != null)
        {
            byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
            req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
            req.GetRequestStream().Close();
        }

        HttpWebResponse resp;
        try
        {
            resp = (HttpWebResponse)req.GetResponse();
        }
        catch (WebException e)
        {
            resp = (HttpWebResponse)e.Response;
        }

        if (resp == null)
        {
            responseBody = null;
            Console.WriteLine("Response is null");
        }
        else
        {
            Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
            foreach (string headerName in resp.Headers.AllKeys)
            {
                Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
            }
            Console.WriteLine();
            Stream respStream = resp.GetResponseStream();
            if (respStream != null)
            {
                responseBody = new StreamReader(respStream).ReadToEnd();
                Console.WriteLine(responseBody);
            }
            else
            {
                Console.WriteLine("HttpWebResponse.GetResponseStream returned null");
            }
        }

        Console.WriteLine();
        Console.WriteLine("  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*  ");
        Console.WriteLine();

        return responseBody;
    }
}
于 2011-10-27T21:10:22.820 に答える