2013-05-31 10 views
12

Mam usług Web.Api który ma metodę, która akceptuje niestandardowej klasy i zwraca inną klasę niestandardowe:Jak mogę wysłać ciasteczko z metody kontrolera Web.Api

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

Teraz chcę także wyślij cookie z powrotem jako część odpowiedzi Http. Jak mogę to zrobić?

Odpowiedz

21

Udało mi się to zrobić, łącząc informacje z kilku różnych lokalizacji. Po pierwsze, aby łatwo móc wysyłać pliki cookie w odpowiedzi kontroler Web.Api powinien powrócić instancję klasy 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; 
    } 
} 

Ale skąd mam mieć pewność, że mogę łatwo TAKŻE wysłać ponownie CustomResponse?

Podstęp jest w answer do tego question. Użyj metody Request.CreateResponse<T> w obiekcie żądania. Cała sprawa staje się wówczas:

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

To wygląda dobrze. Jeśli robisz to w wielu metodach działania, możesz umieścić go w filtrze akcji. –

+1

Byłem "wow ten wspaniały ten api internetowych rzeczy", dopóki nie zobaczyłem tego. Co za wstyd, nie można po prostu dodać pliku cookie bez konieczności zwracania HttpResponseMessage. Pomyślałem, że chodzi o to, aby uczynić Web API łatwiejszym niż WCF. Obawiam się, że tego nie widzę. W jaki sposób filtr akcji może tutaj pomóc, nie dodając jeszcze więcej złożoności do tak prostego wymagania. Nie rozumiem tego. – ianbeks

+0

Przepraszam, jeśli mogę zapytać, jestem nieco zdezorientowany. Czy muszę pobrać plik cookie odpowiedzi w kliencie i ustawić go, lub przeglądarka, która otrzyma nagłówek odpowiedzi zestawu plików cookie, powinna automatycznie to zrobić? –

1

podstawie this post, WebApi getting headers and querystring and cookie values i this post, api net mvc cookie implementation, używam następujące kody do pobierania i ustawiania ciasteczek pod asp.net web api. Działa, gdy serwer działa w IIS Express, powinien działać również wtedy, gdy serwer ma numer IIS. Ale nie wiem, czy to działa, czy nie dla self-hostaweb-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

Miałem ten problem. Ogłosiłem tę samą metodę na dwóch kontrolerach jako publiczne o tej samej nazwie powodującej konflikt.

Te metody nie powinny być metodami sieciowymi. Cieszę się, że to się stało, że przyjąłem kolejny błąd.

Powiązane problemy