2013-05-31 5 views
12

Ho un servizio Web.Api che ha un metodo che accetta una classe personalizzata e restituisce un'altra classe personalizzata:Come posso inviare un cookie da un metodo di controllo Web.Api

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

Ora voglio anche inviare un cookie come parte della risposta Http. Come lo posso fare?

risposta

21

Sono riuscito a farlo combinando le informazioni da alcune posizioni diverse. In primo luogo, in modo da essere facilmente in grado di inviare i cookie nella risposta, il controller Web.Api deve restituire un'istanza della classe 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; 
    } 
} 

Ma allora come faccio a fare in modo che posso facilmente INOLTRE restituire il CustomResponse?

Il trucco è nel answer in questo question. Utilizzare il metodo Request.CreateResponse<T> sull'oggetto richiesta. L'intera faccenda diventa allora:

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

Questo sembra giusto. Se lo fai con molti metodi di azione, puoi inserirlo in un filtro azione. –

+1

Sono stato tutto "wow questa fantastica roba di questo web api" fino a quando non l'ho visto. Che peccato non si può semplicemente aggiungere un cookie senza dover restituire un messaggio HttpResponseMessage. Ho pensato che l'idea fosse di rendere l'API Web più semplice di WCF. Ho paura di non vederlo. Come può un filtro di azione aiutare qui senza aggiungere ancora più complessità a un requisito così semplice. Non capirlo – ianbeks

+0

Scusa se posso chiedere, sono un po 'confuso. Devo prendere il cookie di risposta nel client e impostarlo, oppure il browser che ottiene l'intestazione di risposta del set-cookie dovrebbe farlo automaticamente? –

1

Sulla base this post, WebApi getting headers and querystring and cookie values e this post, api net mvc cookie implementation, io uso seguenti codici per ottenere e impostare i cookie sotto asp.net web api. Funziona quando il server è su IIS Express, dovrebbe funzionare anche quando il server è IIS. Ma non so che funzioni o no per l'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); 
     } 
    } 
} 
0

Aveva questo problema. Ho dichiarato lo stesso metodo su due controller come pubblici con lo stesso nome causando un conflitto.

Questi metodi non dovevano essere metodi Web. Quindi sono contento che questo accaduto abbia colto un altro errore.

Problemi correlati