Как я могу отправить cookie с помощью метода контроллера Web.Api

У меня есть служба Web.Api, которая имеет метод, который принимает пользовательский класс и возвращает другой пользовательский класс:

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

Теперь я хочу также отправить cookie обратно как часть ответа Http. Как я могу это сделать?

Ответ 1

Мне удалось это сделать, объединив информацию из нескольких разных мест. Во-первых, чтобы легко отправлять куки в ответ, контроллер Web.Api должен вернуть экземпляр класса System.Net.Http.HttpResponseMessage (link):

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;
    }
}

Но как я могу убедиться, что я легко могу отправить обратно CustomResponse?

Трюк находится в ответе этому вопросу . Используйте метод 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;
    }
}

Ответ 2

Основываясь на этот пост, WebApi получает заголовки и строки и значения cookie и этот пост, api net mvc cookie, я использую следующие коды для получения и установки файлов cookie в asp.net web api. Он работает, когда сервер находится в IIS Express, он должен работать, когда сервер IIS тоже. Но я не знаю, как это работает или нет для self-host web-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 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); 
        }
    }
}

Ответ 3

Была эта проблема. Я объявил тот же метод на двух контроллерах, что и общедоступный с тем же именем, что и конфликт.

Эти методы не должны быть веб-методами. Поэтому я рад, что это произошло, и у вас появилась еще одна ошибка.