top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Working With Cookies In Web API And HttpClient

+4 votes
433 views

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.

posted Oct 31, 2016 by Shivaranjini

  Promote This Article
Facebook Share Button Twitter Share Button LinkedIn Share Button


Related Articles

In the previous article you learnt to consume a Web API created in ASP.NET Core using jQuery client. Although local clients are quite common in Ajax rich applications, many real-world situations require that you call a Web API from a different application. Thus the client application and the Web API application are different and you can't use JavaScript to call the Web API (due to default browser settings). Moreover, if you wish to call a Web API from a desktop application JavaScript is not an option. In such cases you can use HttpClient to call the Web API. This article tells you how.

I assume that you have the Web API we developed in the earlier parts of this series ready with you. Add a new ASP.NET Core project to the same solution and configure it to use ASP.NET Core MVC. We won't go into the details of that configuration here since that's the basic step for creating any web application under ASP.NET Core.

Once you have the new project configured, open Project.json and add the two dependencies:

"System.Net.Http": "4.3.0-preview1-24530-04",
"Newtonsoft.Json": "9.0.2-beta1"

Notice the System.Net.Http entry. This is a NuGet package that supplies us the HttpClient component. The Json.Net component comes from the Newtonsoft.Json NuGet package and does the trick of JSON serialization and deserialization for us.

Now add a new controller - HomeController - to the project (remember now you are coding in the client application's project, not the Web API project). The HomeController will have seven actions as outlined below:

  • Index() : Returns a view displaying a list of existing customers.
  • Insert() and Insert(obj) : Handle the insert operation by adding a new customer.
  • Update(id) and Update(obj) : Handle the update operation by modifying an existing customer.
  • ConfirmDelete() and Delete() : Handle delete confirmation and delete operations by removing a customer.

In the section that follow I won't discuss the views and their markup in detail. They are quite straightforward and similar to ASP.NET MVC views. Our main interest is the actions that make use of HttpClient component to call the Web API.

Displaying a list of customers

The Index view that displays a list of all the customers looks like this:

image

The Index() action behind this view is shown below:

public ActionResult Index()
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri
("http://localhost:49387");
        MediaTypeWithQualityHeaderValue contentType = 
new MediaTypeWithQualityHeaderValue("application/json");
        client.DefaultRequestHeaders.Accept.Add(contentType);
        HttpResponseMessage response = client.GetAsync
("/api/customerservice").Result;
        string stringData = response.Content.
ReadAsStringAsync().Result;
        List<Customer> data = JsonConvert.DeserializeObject
<List<Customer>>(stringData);
        return View(data);
    }
}

The Index() action creates a new instance of HttpClient and sets its BaseAddress and accept header accordingly. Make sure to change the base address as per your setup. The code then calls the GetAsync() method of HttpClient to invoke the Get() action of the Web API. Since the content type is set to JSON, the Web API will its data in JSON format. This data is unpacked from the HttpResponseMessage object using the ReadAsStringAsync() method. The JSON string is then deserialized into a List of Customer objects using Json.Net component's JsonConvert class.

Adding a new customer

The Insert view that allows you to add a new customer is shown below:

image

The GET and POST versions of the Insert() action are shown below:

public ActionResult Insert()
{
    return View();
}

[HttpPost]
public ActionResult Insert(Customer obj)
{
    ....
    string stringData = JsonConvert.
SerializeObject(obj);
    var contentData = new StringContent
(stringData, System.Text.Encoding.UTF8, 
"application/json");
    HttpResponseMessage response = client.PostAsync
("/api/customerservice", contentData).Result;
    ViewBag.Message = response.Content.
ReadAsStringAsync().Result;
    return View(obj);
    ....
}

The GET version of Insert() simply returns the Insert view to the browser.

The POST version of Insert() first serializes the Customer object received through the model binding into a JSON string. This is necessary because we want to POST data in JSON format. The code then wraps this JSON string into a StringContent object. Notice that the StringContent constructor sets the encoding to UTF8 and media type to JSON. The code then calls the PostAsync() method of HttpClient and submits the JSON data to the Web API using POST verb. The string message returned by the Web API is unwrapped from HttpResponseMessage object using its ReadAsStringAsync() method.

Modify a customer

The Update view looks like this:

image

And the two Update() actions responsible for the relevant functionality are as shown below:

public ActionResult Update(string id)
{
    HttpResponseMessage response = 
client.GetAsync("/api/customerservice/" + id).Result;
    string stringData = response.Content.
ReadAsStringAsync().Result;
    Customer data = JsonConvert.
DeserializeObject<Customer>(stringData);
    return View(data);
}

[HttpPost]
public ActionResult Update(Customer obj)
{
    string stringData = JsonConvert.SerializeObject(obj);
    var contentData = new StringContent(stringData,
System.Text.Encoding.UTF8,"application/json");
    HttpResponseMessage response = client.PutAsync
("/api/customerservice/" + obj.CustomerID, 
contentData).Result;
    ViewBag.Message = response.Content.
ReadAsStringAsync().Result;
    return View(obj);
}

The GET version of Update() action invokes Get(id) of Web API using the GetAsync() method of HttpClient. Notice that this time CustomerID is appended in the URL. The returned Customer object is unpacked using the ReadAsStringAsync() method and the stringified JSON is collected in a string variable. This JSON string is then deserialized into a Customer object using Deserialize() method if JsonConvert.

The POST version of Update() is quite similar to the POST version of Insert() we discussed earlier. However, this time we use PutAsync() method by passing the CustoemrID and the stringified JSON data. The string message is then read using ReadAsStringAsync() as before.

Deleting a customer

 Clicking the Delete links from the Index view takes you to a confirmation page as shown below:

image

The ConfirmDelete() action behind this view is shown below:

public ActionResult ConfirmDelete(string id)
{
    HttpResponseMessage response = 
client.GetAsync("/api/customerservice/" + id).Result;
    string stringData = response.
Content.ReadAsStringAsync().Result;
    Customer data = JsonConvert.
DeserializeObject<Customer>(stringData);
    return View(data);
}

This action is same as the GET version of Update() action.

When you click on the Delete button to delete the selected customer, the page is POSTed to Delete() action:

[HttpPost]
public ActionResult Delete(string customerid)
{
    HttpResponseMessage response = 
client.DeleteAsync("/api/customerservice/" 
+ customerid).Result;
    TempData["Message"] = 
response.Content.ReadAsStringAsync().Result;
    return RedirectToAction("Index");
}

The Delete() action receives the CustomerID through model binding. Remember to emit this value on the ConfirmDelete view using a hidden field (or any other technique of your choice). The code then calls the DeleteAsync() method if the HttpClient to invoke the Delete() action of Web API. The string message returned from the Web API is stored in a TempData entry so that it can be outputted on the Index view.

That's it! This complete the remote client for the Web API. Run the Index view and test all the CRUD operations.

READ MORE

ASP.NET Web API map HTTP verbs to an action method. The Web API actions must follow prescribed signatures in order to work as expected. For example, a Web API method handling POST requests usually takes a single parameter. More often than not this parameter is of a complex type that wraps the actual pieces of data in its properties. This arrangement goes well when you know the exact model being passed by a client (see below).

public string Post(Customer obj)
{
 ...
}

However, this arrangement is of no use when a client is sending arbitrary pieces of data not mapping to any model. Luckily, Web API provides a way to deal with such data. This article discusses just that.

Consider a case where a Web API is expecting data to be inserted in a table from a client. The data in question consists of arbitrary pieces of information and can't be mapped to a predefined model class. In such cases you can make use of FormDataCollection class. The FormDataCollection class resides in System.Net.Http.Formatting namespace and represents a dictionary of arbitrary keys and values.

The FormDataCollection class should not be confused with the FormCollection class of ASP.NET MVC. They reside in different namespaces. The FormDataCollection resides in System.Net.Http.Formatting whereas FormCollection resides in System.Web.Mvc namespace.

So, a client can send any number of arbitrary key-value pairs to the Web API and the Web API will receive them as a FormDataCollection. The following Post() method of Web API shows how this is done:

public string Post(FormDataCollection form)
{
    string customerid = form.Get("customerId");
    string company = form.Get("companyName");
    string contact = form.Get("contactName");
    string country = form.Get("country");

    NorthwindEntities db = new NorthwindEntities();
    Customer obj = new Customer()
    {
        CustomerID = customerid,
        CompanyName = company,
        ContactName = contact,
        Country = country
    };
    db.Customers.Add(obj);
    db.SaveChanges();

    return "Customer added successfully!";

}

The Post() method shown above takes a parameter of type FormDataCollection. To read the values from this collection you use Get() method and specify a key name. In the above code the client is sending Customer details such as CustomerID, CompanyName, ContactName and Country. Based on these details a Customer object is formed and added to the Customers DbSet. The changes are saved to the database using SaveChanges(). The Post() method then returns a success method to the client.

To call this Web API method you will write the following jQuery code:

$(document).ready(function () {
  var data = {};
  data.customerID = "ABCDE";
  data.companyName = "Company 1";
  data.contactName = "Contact 1";
  data.country = "USA";

  $.post("/api/customer", data, function(msg){
     alert(msg);
  });
  
});

As you can see the above code creates a JavaScript object with four properties - customerID, companyName, contactName and country. Although this class mimics the Customer model class that's not necessary. You can add any arbitrary property - value pairs to this object and send it to the Web API.

Once the data object created $.post() method of jQuery is used to call the Web API and the data object is passed to it. The success function displays the message returned from the Web API.

If you run this application you will see the customerID, companyName, contactName and country values in the FormDataCollection.

image

In the preceding example, you created a JavaScript object and passed it to the $.post() method. There can be a situation where you need to pass the data from form fields (rather than from a JavaScript object) to the Web API. For example, you might be having a web page that renders arbitrary form fields using jQuery based on some condition.

<form id="form1">
    <input type="text" name="customerId" value="ABCDE" />
    <input type="text" name="companyName" value="Company 2" />
    <input type="text" name="contactName" value="Contact 2" />
    <input type="text" name="country" value="USA"  />
</form>

In such cases your $.post() call will change as follows:

$.post("/api/customer", $("#form1").serialize(), function (msg) {
    alert(msg);
});

Notice that the second parameter is not a JavaScript object. It's a call to jQuery serialize() method. The serialize() method returns a URL encoded string that contains the form field name - value pairs. Upon reaching the Web API this data can be read into the FormDataCollection as before.

READ MORE

Whenever you access ASP.NET Web API from your client side script (JavaScript / jQuery) by default the data is returned in JSON format. However, in certain cases you may want to retrieve the data in XML format instead of JSON. On the server side, Web API determinses what data format to use for sending data to the client by doing what is known as Content Negotiation. Simply put, content negotiation is a process by which Web API inspects the incoming request and HTTP headers accompanying the request to figure out what response format(s) the client can understand. Based on this checking Web API sends the output. Two HTTP headers that play role in content negotiation are:

  • Accept
  • Content-Type

To understand how content negotiation works let's create a simple Customer Web API that returns customer data from the Northwind database.

Begin by creating a new ASP.NET MVC 4 project in Visual Studio 2012. You will need to add ADO.NET Entity Framework data model for the Customers table. The following figure shows the Customer class upon adding the data model.

image

Next, add a new Web API controller to the Controllers folder and name it as CustomerController. The CustomerController needs to have just one method - Get() - as shown below:

public class CustomerController : ApiController
{
  public IEnumerable<Customer> Get()
  {
    NorthwindEntities db=new NorthwindEntities();
    var data = (from item in db.Customers
    select item).Take(10);
    return data;
  }
}

As you can see the Get() method simply returns first 10 Customer records from the Customers table. To call this Web API from a client browser, add a new controller and name it as HomeController. Then add a view for the Index() action method of the HomeController.

public class HomeController : Controller
{
  public ActionResult Index()
  {
    return View();
  }
}

Inside the Index view, add the following jQuery code that calls the Customer Web API:

$(document).ready(function () {
  var options = {};
  options.url = "/api/customer";
  options.type = "GET";
  options.success = OnSuccessJSON;
  options.error = OnError;
  $.ajax(options);
});

function OnSuccessJSON(results) {
  var html = "<table border=1 cellpadding=3>";
  for (var i = 0; i < results.length; i++) {
    html += "<tr>";
    html += "<td>" + results[i].CustomerID + "</td>";
    html += "<td>" + results[i].CompanyName + "</td>";
    html += "</tr>";
  }
  html += "</table>";
  $("#container").html(html);
}

function OnError(err) {
  alert(err.status + " - " + err.statusText);
}

The above code uses $.ajax() of jQuery to call the Customer Web API. The options object stores all the settings that are needed to call our Web API. Notice that currently we have not specified Accept and Content-Type headers. The OnSuccessJSON() function handles the successful request and displays the returned data in an HTML table. As mentioned earlier, by default Web API invoked via client side script gets data from the server in JSON format. That is why the OnSuccessJSON() function treats results object like any other JSON array. After generating HTML markup for table the markup is set to the container <div> element.

The OnError() function is called in case there is any error while calling the Web API.

If you run the above view you should see the HTML table populated with customer data as shown below:

image

 Now let's modify our jQuery code so that the Web API sends us data in XML format instead of JSON. Modify the options object to include Accept header as shown below:

 ...
options.type = "GET";
options.headers = { "accept": "application/xml;charset=utf-8" };
...

As you can see you use the headers setting. Set its key to accept and value to application/xml;charset=utf-8. This value tells Web API that data should be sent in XML format. You will also need to write another success handler function because now the data is in XML format instead of JSON. Let's call that function OnSuccessXML().

function OnSuccessXML(results) {
  var html = "<table border=1 cellpadding=3>";
  $(results).find("Customer").each(function () {
    var item = $(this);
    html += "<tr>";
    html += "<td>" + item.find("CustomerID").text() + "</td>";
    html += "<td>" + item.find("CompanyName").text() + "</td>";
    html += "</tr>";
  });
  html += "</table>";
  $("#container").html(html);
}

The OnSuccessXML() function uses find() of jQuery to locate <Customer> elements from the response XML and for each <Customer> the code specified inside each() is executed. The each() function further finds <CustomerID> and <CompanyName> elements from the response XML and an HTML table is generated. Finally, the generated HTML markup is assigned to the container <div> element.

Make sure to change the success function and then run the new code:

 ...
options.success = OnSuccessXML;
... 

In the above code you used Accept header but what's the role of Content-Type header? The Content-Type header is used in situations where response format as suggested by Accept header can't be sent. To understand this modify the jQuery code as shown below:

...
options.type = "GET";
options.contentType = "application/json;charset=utf-8";
options.headers = { "accept": "application/xml123;charset=utf-8" };
...

Notice carefully that accept header contains invalid format (xml123) and contentType setting says the format to be JSON. In this case since xml123 is an unsupported format, Web API will use format as suggested by Content-Type header (JSON in this case). You can confirm this by wiring OnSuccessJSON() function again.

The following table summarizes various combinations of Accept and Content-Type headers:

AcceptContent-TypeResponse Format
YesNoAs per Accept header value
YesYesAs per Accept header value
Yes but invalidYesAs per Content-Type header value
NoYesAs per Content-Type header value
No or invalidNo or invalidDepending on the default sequence of media formatters specified in the Configuration.Formatters list.

The last option from the above table can be changed via Web API code but that's beyond the scope of this article.

That's it! Keep coding !!

READ MORE

ASP.NET developers commonly use forms authentication to secure their web pages. Just like ASP.NET web forms and ASP.NET MVC applications, Web API can take advantage of forms authentication to implement authentication and role based security. I have already explained how forms authentication works in web forms and MVC applications. In this post I explain how forms authentication can be used in Web API being consumed in an MVC application. This example assumes that the Web API and the View that consumes it using jQuery are parts of the same project (that is they belong to the same origin).

The overall process of implementing forms authentication remains the same in case of Web API also. However, there are a few points that you need to keep in mind:

  • Web API itself doesn't log-in or log-out a user. That is taken care by the underlying web application - be it web forms application or MVC application. Typically a user logs into the application using some web form or a view designed for that purpose and then proceeds to call a Web API.
  • The Web API action methods can check the authentication status of a user, his membership information and also his role information.
  • If an unauthenticated user tries to access a Web API that requires authentication you typically get "undefined" error in the browser (you will see this later).

Configure SQL Server

Membership features of ASP.NET require certain database tables and stored procedures. To configure your SQL server database for enabling application services (membership, roles, profiles) you use aspnet_regsql.exe command line tool. We won't discuss this tool here because its usage is exactly the same as in the case of web forms and MVC applications. You can also let ASP.NET configure and create a new LocalDb database for you if you don't want to use an existing database. If so, skip this step and move to the next.

Configure Web API project to use forms authentication

Now create a new ASP.NET MVC 4 project and select Web API as its project template. Then open its web.config file and add the following markup to it:

<authentication mode="Forms">
  <forms loginUrl="~/home/login" defaultUrl="~/home/index" ></forms>
</authentication>

The <authentication> section sets the mode of authentication and in this case it is set to Forms. The <forms> tag configures the loginUrl and defaultUrl attributes to ~/home/login and ~/home/index respectively. The loginUrl attribute indicates URL of the login page whereas defaultUrl attribute indicates URL of the default page.

If you haven't configured a database to store membership information and don't want to use an existing database, select PROJECT > ASP.NET Configuration to open Website Administration Tool. Click on the security tab of the tool and create two roles - Administrator and Operator. Then create two users - user1 and user2 - and associate them with Administrator and Operator roles respectively.

image

This will add a new LocalDb database to the App_Data folder and will also add membership, roles and profile providers in the web.config as shown below:

<membership defaultProvider="DefaultMembershipProvider">
      <providers>
        <add name="DefaultMembershipProvider" 
         type="System.Web.Providers.DefaultMembershipProvider,... />
      </providers>
    </membership>

    <roleManager enabled="true" defaultProvider="DefaultRoleProvider">
      <providers>
        <add name="DefaultRoleProvider" 
         type="System.Web.Providers.DefaultRoleProvider... />
      </providers>
    </roleManager>

    <profile defaultProvider="DefaultProfileProvider">
      <providers>
        <add name="DefaultProfileProvider" 
         type="System.Web.Providers.DefaultProfileProvider... />
      </providers>
    </profile>

As you can see the membership, roles and profile providers are being picked from System.Web.Providersnamespace.

Create Login and Logout views

Since we have created users through WAT tool as mentioned in the preceding section there is no need to create registration page. You can directly create Login and Logout actions and views. To do so, open the HomeController from the controllers folder and add the following actions to it:

public ActionResult Login()
{
return View();
}

[HttpPost]
public ActionResult Login(string userid,string password)
{
  if (Membership.ValidateUser(userid, password))
  {
    FormsAuthentication.SetAuthCookie(userid, false);
    Response.Redirect(FormsAuthentication.DefaultUrl);
  }
  return View();
}

public ActionResult Logout()
{
  return View();
}

[HttpPost]
public ActionResult DoLogout()
{
  FormsAuthentication.SignOut();
  Response.Redirect(FormsAuthentication.LoginUrl);
  return View();
}

The Login(), Logout() and DoLogout() methods are easy to understand. The second version of Logn() method accepts userid and password parameters. Inside, it uses ValidateUser() method of Membership class to check whether a user has supplied valid credentials. If so, a forms authentication cookie is set using SetAuthCookie() method of FormsAuthentication class. The user is then redirected to default page (/home/index in this case).

The DoLogout() method removes the forms authentication cookie using Signout() method of FormsAuthentication class and takes the user to login page (/home/login in this case).

The Login and Logout views are quite simple in nature and are shown below:

image 

 

image

 

Create a Web API

Now let's create a simple Web API for testing purpose. One the default ValuesController class and modify it as shown below:

public class ValuesController : ApiController
{
  [Authorize]
  public IEnumerable<string> Get()
  {
    if (User.Identity.IsAuthenticated)
    {
      MembershipUser user = Membership.GetUser();
      if (Roles.IsUserInRole(user.UserName, "Administrator"))
      {
         return new string[] { "Blue", "Red" };
      }
      else
      {
         return new string[] { "Orange", "White" };
      }
    }
    else
    {
        throw new Exception("You are not authorized to use this page!");
    }
}

As you can see the ValuesController inherits from ApiController and contains Get() method. The Get() method returns an IEnumerable of strings and responds to GET requests. Notice that the Get() method is decorated with [Authorize] attribute. Remember that this [Authorize] attribute comes from System.Web.Http namespace whereas [Authorize] used in normal MVC controller comes from System.Web.Mvc namespace. The [Authorize] attribute indicates that the Get() method can be accessed only by authenticated users.

Inside the Get() method User.Identoty.IsAuthenticated is used as an additional check to ensure that the desired code is executed only for an authenticated user. Then the code implements role based security and checks whether current user belongs to Administrator role or not. This is done using IsUserInRole() method of Roles class. Accordingly a string array containing some color values (Blue and Red for administrators and Orange and White for other users) is returned to the caller. If a request is not authenticated an exception is thrown.

Consume the Web API

The jQuery code that calls the Web API resides inside Index view and is shown below:

$(document).ready(function () {
  $("#button1").click(function () {
    $.ajax({
      url: '/api/values',
      type: 'GET',
      success: function (r) { alert('Success : ' + r); },
      error: function (err) { alert('Error : ' + err.description); }
    });
  });
});

As you can see the click event handler of a button (button1) invokes values web API using $.ajax() of jQuery. The success function displays the returned array of colors in an alert dialog. Similarly, the error function displays the error information in an alert dialog.

If you try to invoke the web API without first signing in to the system you will get the following error:

image

If you log in to the system and then invoke the web API you will get the color array as shown below:

image

READ MORE

Most of the times developers use jQuery $.ajax() to call ASP.NET Web API from the client side script. At times, however, you may need to use plain JavaScript to invoke the Web API. Consider a situation wherein you wish to call Web API from HTML5 Web Worker. Now, you can't use jQuery to accomplish your task because DOM access is not allowed inside a web worker. Another reason might be that your project don't have any dependency on jQuery or such libraries. Luckily, calling a Web API using XMLHttpRequest object and plain JavaScript is not hard. This article discusses how that can be done with a sample Customer Web API.

In this example you will use a Customer Web API that does CRUD operations on the Customers table of Northwind database. This Web API is shown below:

public class CustomerController : ApiController
{
    NorthwindEntities db = new NorthwindEntities();

    public List<Customer> Get()
    {
        return db.Customers.ToList();
    }

    public Customer Get(string id)
    {
        return db.Customers.Find(id);
    }

    public string Post(Customer obj)
    {
        db.Customers.Add(obj);
        db.SaveChanges();
        return "Customer added successfully!";
    }

    public string Put(string id,Customer obj)
    {
        db.Entry(obj).State = EntityState.Modified;
        db.SaveChanges();
        return "Customer modified successfully!";
    }

    public string Delete(string id)
    {
        db.Entry(db.Customers.Find(id)).State = EntityState.Deleted;
        db.SaveChanges();
        return "Customer deleted successfully!";
    }
}

As you can see CustomerController consists of five methods namely Get(), Get(id), Post(), Put() and Delete(). These methods deal with the GET, GET, POST, PUT and DELETE verbs respectively.

To call this Web API from client side script you will create a JavaScript object - AjaxHelper - that consists of five methods namely SelectAll(), SelectByID(), Insert(), Update() and Delete(). You will then call t these methods to invoke the respective Web API action.

The AjaxHelper object is shown below:

function AjaxHelper(baseUrl)
{
    this._baseUrl = baseUrl;

    var callWebAPI = function (url, verb, data, callback) {

        var xhr = new XMLHttpRequest();

        xhr.onload = function (evt) {
            var data = JSON.parse(evt.target.responseText);
            callback(data);
        }

        xhr.onerror = function () {
            alert("Error while calling Web API");
        }

        xhr.open(verb, url);
        xhr.setRequestHeader("Content-Type", "application/json");
        if (data==null) {
            xhr.send();
        }
        else {
            xhr.send(JSON.stringify(data));
        }
    }

    this.SelectAll = function (callback) {
        callWebAPI(this._baseUrl, "GET", null, callback);
    }

    this.SelectByID = function (id, callback) {
        callWebAPI(this._baseUrl + "/" + id, "GET", null, callback);
    }

    this.Insert = function (obj, callback) {
        callWebAPI(this._baseUrl, "POST", obj, callback);
    }

    this.Update = function (id, obj, callback) {
        callWebAPI(this._baseUrl + "/" + id, "PUT", obj, callback);
    }

    this.Delete = function (id, callback) {
        callWebAPI(this._baseUrl + "/" + id, "DELETE", null, callback);
    }
}

The AjaxHelper object receives base URL of the Web API as its constructor parameter and stores it in a _baseUrl private variable. Then the code shows a private helper function - callWebAPI() - that creates and configures a new instance of XMLHttpRequest object. The callWebAPI() function accepts four parameters - url, verb, data and callback - and configures five aspects of the XMLHttpRequest object:

  • It wires a success function by handling the load event of the XMLHttpRequest.
  • It wires an error function by handling the error event of the XMLHttpRequest.
  • It opens a URL for a specific HTTP verb using open() method.
  • It sets the content-type header to application/json since we will be using JSON format for the communication.
  • It calls the send() method by passing the data parameter.

Notice the onload event handler. It retrieves the data returned by the Web API using responseText property (which will be in JSON format) and parses it into JavaScript object. The callback parameter supplies a callback function that will be invoked with the Web API call succeeded.

Then the code shows a series of functions of the AjaxHelper object. The SelectAll(), SelectByID(), Insert(), Update() and Delete() methods call the callWebAPI() function by passing the required URL, HTTP verb, data and callback.

You can now use the AjaxHelper object as shown below:

var ajaxHelper = new AjaxHelper("/api/customer");

var selectAllCallback = function (customers) {
    alert(customers.length);
}

var selectByIDCallback = function (customer) {
    alert(customer.CompanyName);
}

var actionCallback = function (msg) {
    alert(msg);
}

//GET
ajaxHelper.SelectAll(selectAllCallback);
ajaxHelper.SelectByID("ALFKI", selectByIDCallback);

//POST
var obj = {
    CustomerID: "ABCDE",
    CompanyName: "Company 1",
    ContactName: "Contact 1",
    Country: "USA"
}
ajaxHelper.Insert(obj, actionCallback);

//PUT
obj.CompanyName = "Company 2";
ajaxHelper.Update("ABCDE", obj, actionCallback);

//DELETE
ajaxHelper.Delete("ABCDE", actionCallback);

As you can see calling a Web API is now a matter of invoking the methods of AjaxHelper object. The callback functions simply display an alert() that confirms that the underlying operation was successful.

READ MORE
...