miso_soup3 Blog

主に ASP.NET 関連について書いています。

ASP.NET HttpResponse.Cookies.Add で HttpRequest.Cookies にも反映される件

ASP.NET MVC 上で、Cookie を Response(System.Web.HttpResponseBase) に追加した後、Request(System.Web.HttpRequestBase) の Cookie にもその値が追加されます。

アクションメソッドのサンプルコードです。

using System.Diagnostics;
using System.Web;
using System.Web.Mvc;

namespace CookieTest2.Controllers
{
    public class MyMvcController : Controller
    {
        public ActionResult Get()
        {
            //取得
            {
                string requestCookie = Request.Cookies["abcd"]?.Value;
                Debug.WriteLine("mvc 取得:" + requestCookie);
            }

            //書きこむ
            var cookie = new HttpCookie("abcd", "write-value");
            cookie.Path = "/";
            Response.Cookies.Add(cookie);

            //取得2
            {
                string requestCookie = Request.Cookies["abcd"]?.Value;
                Debug.WriteLine("mvc 取得2:" + requestCookie);
            }
            return View();

            //クッキーを送信していないとき
            /*
            mvc 取得:
            mvc 取得2:write-value
            */
        }
    }
}

ブラウザ側からクッキーが送信されない状態で実行すると、↓のように出力されます。

mvc 取得:
mvc 取得2:write-value

MSDN HttpResponse.Cookies Property によると、
Response.Cookies に追加すると、Request.Cookies の方にすぐに反映されるとのこと。

After you add a cookie by using the HttpResponse.Cookies collection, the cookie is immediately available in the HttpRequest.Cookies collection, even if the response has not been sent to the client.

これはひどい。ASP.NET 界隈では有名な話?

ASP.NET Web API では

ASP.NET Web API においては、System.Web 側のオブジェクトをつかわない限りは上記のことは起きません。
Cookie の読み書きのコードを見れば MVC よりかは明らかです。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;

namespace CookieTest2.Controllers
{
    public class MyApiController : ApiController
    {
        [Route("myapi")]
        public HttpResponseMessage Get()
        {
            //取得
            {
                var requestCookie = Request.Headers.GetCookies("abcd").FirstOrDefault()?["abcd"]?.Value;
                Debug.WriteLine("api 取得:" + requestCookie);
            }

            //書きこむ
            var cookie = new CookieHeaderValue("abcd", "write-value");
            cookie.Path = "/";
            cookie.Expires = DateTime.Now.AddDays(1);

            var response = Request.CreateResponse(HttpStatusCode.OK);
            response.Headers.AddCookies(new CookieHeaderValue[] { cookie });

            //取得2
            {
                var requestCookie = Request.Headers.GetCookies("abcd").FirstOrDefault()?["abcd"]?.Value;
                Debug.WriteLine("api 取得2:" + requestCookie);
            }

            return response;

            /*
            クッキーが送信されない場合
            api 取得:
            api 取得2:
            */
        }

出力:

api 取得:
api 取得2:


間違いです→ただし、Global.asax 上(IHttpHandlerが動く前のイベントとか)で、HttpResponse.Cookies(System.Web 配下)に Cookie を追加すると、↑の ApiController 上の Request.Cookies(System.Net.Http 配下)にて取得できますので注意。(確かかどうかちょっと確認中