C# 如何从 Web.Api 控制器方法发送 cookie

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16854376/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 07:56:55  来源:igfitidea点击:

How can I send a cookie from a Web.Api controller method

c#cookiesasp.net-web-api

提问by user1429080

I have a Web.Api service which has a method that accepts a custom class and returns another custom class:

我有一个 Web.Api 服务,它有一个接受自定义类并返回另一个自定义类的方法:

public class TestController : ApiController
{
    public CustomResponse Post([FromBody]CustomRequest request)
    {
        // process request
        ...
        // create response
        CustomResponse resp = new CustomResponse() { ... };
        return resp;
    }
}

Now I want to also send a cookie back as part of the Http response. How can I do that?

现在我还想将 cookie 作为 Http 响应的一部分发回。我怎样才能做到这一点?

回答by user1429080

I managed to do this by combining information from a few different locations. First, in order to easily be able to send cookies in the response, the Web.Api controller should return an instance of the System.Net.Http.HttpResponseMessageclass (link):

我通过结合来自几个不同位置的信息设法做到了这一点。首先,为了能够轻松地在响应中发送 cookie,Web.Api 控制器应该返回一个System.Net.Http.HttpResponseMessage类的实例(链接):

public class TestController : ApiController
{
    public HttpResponseMessage Post([FromBody]CustomRequest request)
    {
        var resp = new HttpResponseMessage();
        ...

        //create and set cookie in response
        var cookie = new CookieHeaderValue("customCookie", "cookieVal");
        cookie.Expires = DateTimeOffset.Now.AddDays(1);
        cookie.Domain = Request.RequestUri.Host;
        cookie.Path = "/";
        resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });

        return resp;
    }
}

But then how do I make sure that I can easily ALSO send back the CustomResponse?

但是,我如何确保我也可以轻松地将CustomResponse.

The trick is in the answerto this question. Use the Request.CreateResponse<T>method on the request object. The whole deal then becomes:

诀窍在于这个问题答案。在请求对象上使用该方法。整个交易就变成了:Request.CreateResponse<T>

public class TestController : ApiController
{
    public HttpResponseMessage Post([FromBody]CustomRequest request)
    {
        // process request
        ...

        var resp = Request.CreateResponse<CustomResponse>(
            HttpStatusCode.OK,
            new CustomResponse() { ... }
        );

        //create and set cookie in response
        var cookie = new CookieHeaderValue("customCookie", "cookieVal");
        cookie.Expires = DateTimeOffset.Now.AddDays(1);
        cookie.Domain = Request.RequestUri.Host;
        cookie.Path = "/";
        resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });

        return resp;
    }
}

回答by AechoLiu

Based on this post, WebApi getting headers and querystring and cookie valuesand this post, api net mvc cookie implementation, I use following codes to get and set cookies under asp.net web api. It works when the server is on IIS Express, it should work when the server is IIStoo. But I don't know it works or not for self-hostweb-api.

基于这篇文章,WebApi 获取标题和查询字符串和 cookie 值以及这篇文章,api net mvc cookie 实现,我使用以下代码在asp.net web api. 当服务器在 IIS Express 上时它可以工作,当服务器也是IIS如此时它也应该工作。但我不知道它是否适用于self-hostweb-api

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;

namespace System.Web.Http
{

    /// <summary>
    /// Extends the HttpRequestMessage collection
    /// </summary>
    public static class HttpRequestMessageExtensions
    {
        /// <summary>
        /// Returns a dictionary of QueryStrings that's easier to work with 
        /// than GetQueryNameValuePairs KevValuePairs collection.
        /// 
        /// If you need to pull a few single values use GetQueryString instead.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetQueryStrings(this HttpRequestMessage request)
        {
            return request.GetQueryNameValuePairs()
                          .ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase);
        }

        /// <summary>
        /// Returns an individual querystring value
        /// </summary>
        /// <param name="request"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetQueryString(this HttpRequestMessage request, string key)
        {
            // IEnumerable<KeyValuePair<string,string>> - right!
            var queryStrings = request.GetQueryNameValuePairs();
            if (queryStrings == null)
                return null;

            var match = queryStrings.FirstOrDefault(kv => string.Compare(kv.Key, key, true) == 0);
            if (string.IsNullOrEmpty(match.Value))
                return null;

            return match.Value;
        }

        /// <summary>
        /// Returns an individual HTTP Header value
        /// </summary>
        /// <param name="request"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetHeader(this HttpRequestMessage request, string key)
        {
            IEnumerable<string> keys = null;
            if (!request.Headers.TryGetValues(key, out keys))
                return null;

            return keys.First();
        }

        /// <summary>
        /// Retrieves an individual cookie from the cookies collection
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cookieName"></param>
        /// <returns></returns>
        public static string GetCookie(this HttpRequestMessage request, string cookieName)
        {
            CookieHeaderValue cookie = request.Headers.GetCookies(cookieName).FirstOrDefault();
            if (cookie != null)
                return cookie[cookieName].Value;

            return null;
        }

        public static void SetCookie(this ApiController controller, string cookieName, string cookieValue)
        {
            HttpCookie cookie = new HttpCookie(cookieName, cookieValue);
            HttpContext.Current.Response.Cookies.Add(cookie); 
        }
    }
}

回答by Simon Mourier

With recent versions of Web API, async, and IHttpActionResult, we can now simply do this:

使用最新版本的 Web API、async、 和IHttpActionResult,我们现在可以简单地执行以下操作:

public async Task<IHttpActionResult> MyMethod(... myParameters ...)
{
    ...
    var cookie = new CookieHeaderValue("myCookie", "myValue");
    ...

    var resp = new HttpResponseMessage();
    resp.StatusCode = HttpStatusCode.OK;
    resp.Headers.AddCookies(new[] { cookie });
    return ResponseMessage(resp);
}