Multiple Instances of Partial Pa
Working with Cookies in Web API and HttpClient
ASP.NET applications often use cookies to store user specific pieces of
information. Not just web forms and MVC applications, Web API too can use
cookies. Sometimes developers device an authentication scheme revolving around
cookie as an authentication ticket. Although this article won't show you how to
develop such a scheme, it illustrates how cookies can be issued and used in Web
API. Specifically you will learn:
- How to set cookies from a Web API controller and read those cookies in a
client application.
- How to set cookies from a client application (HttpClient) and read those
cookies in a Web API controller.
Setting cookie from Web API controller and reading it in the client
To work through the code shown in this section create a new Web API project
and write a Get() method as shown below:
public HttpResponseMessage Get()
{
CookieHeaderValue serverCookie = new CookieHeaderValue
("server_cookie", "hello from server");
serverCookie.Expires = DateTimeOffset.Now.AddDays(2);
serverCookie.Domain = Request.RequestUri.Host;
serverCookie.Path = "/";
HttpResponseMessage response = Request.CreateResponse
("This is response from the Web API.");
response.Headers.AddCookies(new CookieHeaderValue[] { serverCookie });
return response;
}
The above code shows Get() method that handles GET requests. The method
returns HttpResponseMessage. Inside, the code creates an instance of
CookieHeaderValue class. This class represents a cookie header that goes as a
part of HTTP headers. The constructor of the CookieHeaderValue class accepts a
cookie name (server_cookie in this case) and its value (hello from server - in
this case). The code then sets Expires, Domain and Path properties of the
cookie. The Expires property sets the expiration date and time for the cookie (2
days from now in this case). The Domain property is set to the Hose of the
request and the Path property is set to the root ("/").
Then the code creates a instance of HttpResponseMessage class using the
CreateResponse() method of the Request object. The CreateResponse() method
accepts the response data (a string message in this case) and returns it wrapped
in a HttpResponseMessage.
The CookieHeaderValue object created earlier is then added to the Headers
collection of the HttpResponseMessage. This is done using the AddCookies()
method and then passing an array of CookieHeaderValue objects. In this case we
are issuing just one cookie and hence the array contains just a single element.
Finally, the HttpResponseMessage is returned to the caller.
Now, let's see how this cookie can be read in the client code. It is assumed
that the client application is a separate ASP.NET MVC application and uses
HttpClient to invoke the Web API. The client code to read the cookie is shown
below:
public ActionResult Index()
{
WebRequestHandler handler = new WebRequestHandler();
handler.CookieContainer = new System.Net.CookieContainer();
handler.UseCookies = true;
handler.UseDefaultCredentials = true;
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri("http://localhost:49308/");
HttpResponseMessage response = client.GetAsync("/api/mywebapi").Result;
string data = response.Content.ReadAsAsync<string>().Result;
int count = handler.CookieContainer.Count;
Cookie serverCookie = handler.CookieContainer.
GetCookies(new Uri("http://localhost:49308/"))
["server_cookie"];
ViewBag.CookieCount = count;
ViewBag.ServerResponse = data;
ViewBag.ServerCookieValue = Server.UrlDecode(serverCookie.Value);
return View();
}
The Index() action method shown above creates an instance of
WebRequestHandler class. This class is required because it wraps a
CookieContainer object that stores the cookies during the communication. The
CookieContainer object is instantiated to a new instance of the CookieContainer.
The UseCookies and UseDefaultCredentials properties of the WebRequestHandler are
set to true.
Then an instance of HttpClient is created by passing the WebRequestHandler
object in its constructor. This way the HttpClient object uses the handler
object to store cookies. The BaseAddress property of the HttpClient is set to
the base address of the Web API. Make sure to change this address to reflect
your development environment.
Then GetAsync() method of HttpClient is used to invoke the Get() Web API
method. Note that the above code assumes that the Web API controller is MyWebAPI.
Change the Web API name to match your environment. To read the response sent by
the Web API ReadAsAsync() method is used. In this case the response will be a
string - This is response from the Web API (refer the Web API earlier).
To access the cookie issued by the Web API controller the CookieContainer
object of the WebRequestHandler is used. The Count property of the
CookieContainer returns the number of cookies present in the container. The
GetCookies() method is used to retrieve the server_cookie from the container.
The cookie is returned as Cookie object. The Value property of the Cookie object
returns the value of the cookie. In this case the value will be - hello from
server (see Web API code earlier).
The cookie count, response data and the cookie value are sent to the View
through the respective ViewBag properties. If you output these ViewBag
properties on the Index view you should get the values as expected.
Setting Cookie through HttpClient and reading it in the Web API
In the preceding example the cookie was set in the Web API and was read in
the client application. In this section we will do the opposite - we will set a
cookie from the client application and read it in the Web API.
The following code shows the client side code in the form of an action method
(recollect that our client is an MVC application).
public ActionResult Index()
{
WebRequestHandler handler = new WebRequestHandler();
handler.CookieContainer = new System.Net.CookieContainer();
handler.UseCookies = true;
handler.UseDefaultCredentials = true;
Cookie clientCookie = new Cookie("client_cookie", "hello from client");
clientCookie.Expires = DateTime.Now.AddDays(2);
clientCookie.Domain = Request.Url.Host;
clientCookie.Path = "/";
handler.CookieContainer.Add(clientCookie);
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri("http://localhost:49308/");
HttpResponseMessage response = client.GetAsync("/api/mywebapi").Result;
string data = response.Content.ReadAsAsync<string>().Result;
ViewBag.ServerResponse = data;
return View();
}
Notice the code marked in bold letters. This code creates a Cookie instace
named client_cookie and sets its value to - hello from client. The Expires,
Domain and Path properties of the cookie are set as before. This Cookie is then
added to the CookieContainer object. Finally, Web API is invoked using a GET
request. The response from the Web API is stored in a ViewBag property and
outputted on the view.
The Web API Get() method in this case is modified as follows:
public HttpResponseMessage GetCustomers()
{
CookieHeaderValue clientCookie = Request.Headers.GetCookies
("client_cookie").SingleOrDefault();
string clientCookieValue = clientCookie["client_cookie"].Value;
HttpResponseMessage response = Request.CreateResponse
("Client cookie said - " + clientCookieValue);
return response;
}
Notice the code shown in bold letters. The cookie issued from the client side
is retrieved using the GetCookies() method of the Headers collection. The cookie
is returned as CookieHeaderValue. The value of the cookie can then be read using
the Value property. Just to conform that the value is retrieved successfully the
same value is appended to the response message.
If you wish to access the same cookie across multiple Web API calls (and in
most cases you would need this) you must preserve the WebRequestHandler instance
somewhere (such as a Session variable). This way you can use the same
CookieContainer across multiple Web API calls.
That's it! Run the sample code shown above and test both the scenarios.