Click here to Skip to main content
15,881,898 members
Articles / Web Development / HTML

Calling a RESTful Service like ASP.NET WebApi using WebApiClient

Rate me:
Please Sign up or sign in to vote.
4.78/5 (11 votes)
9 Jul 2014CPOL2 min read 40.8K   507   37   13
In this first tutorial, we are going to learn how to make calls to a Web Api Rest Service using the NuGet Package WebApiRestService.WebApiClient

Introduction

In this first tutorial, we are going to learn the basics on how to make calls to a Web Api Rest Service using the NuGet Package WebApiRestService.WebApiClient.

What is WebApiClient?

WebApiClient is a simple and powerful .NET Portable Library built to work as a middle layer between your application and a RESTFul service, like the Microsoft WebApi. It provides methods to make asynchronous, typed WebApi requests using the HttpClient class. It takes care of all the logic to create the request, wait for the response, handle exceptions and convert the response into an object, leaving you free of writing repetitive code.

Features

  • It is portable. Supports .NET Framework 4.5+, Windows 8+ Apps, Windows Phone Silverlight 8+
  • Supports any kind of RESTful service, not only Microsoft WebApi
  • Ready to work with services that use ASP.NET Identity security
  • Easy installation using NugGet
  • Supports Json and Xml serialization/deserialization
  • Supports the verbs GET, POST, PUT and DELETE
  • Easy to extend functionalities
  • Comes with WindowsIntegratedAuthentication (Negotiate, NTLM, Basic, Kerberos) and BearerTokenAuthentication
  • Easy to send or receive cookies

Resources

You can find more info and examples at: http://webapiclient.azurewebsites.net
To download the NuGet Package: https://www.nuget.org/packages/WebApiRestService.WebApiClient

Using the code

First of all, you need to set up a solution, containing at least 3 projects:

  1. A WebApi Project
  2. A MVC project (the project type you'll choose is up to you)
  3. A Class Library Project, to accomodate the DTO objects

In the Class Library Project

  • create the following class:
C#
public class Restaurant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
}

In the WebApi Project

  • add a reference to the DTO Class Library Project you just created in the last step.
  • create a controller called RestaurantController, and paste this class:
C#
public class RestaurantController : ApiController
{
    List<Restaurant> restaurants = new List<Restaurant>() {
        new Restaurant(){ Id = 1, Name = "Restaurant 1", Address = "1111 Oxford Street" },
        new Restaurant(){ Id = 2, Name = "Restaurant 2", Address = "2222 Oxford Street" },
        new Restaurant(){ Id = 3, Name = "Restaurant 3", Address = "3333 Oxford Street" },
        new Restaurant(){ Id = 4, Name = "Restaurant 4", Address = "4444 Oxford Street" }
    };

    // GET: api/Restaurant
    public IEnumerable<Restaurant> Get()
    {
        return restaurants;
    }
    
    // GET: api/Restaurant/5
    public Restaurant Get(int id)
    {
        return restaurants.SingleOrDefault(r => r.Id == id);
    }

    // POST: api/Restaurant
    public void Post([FromBody]Restaurant value)
    {
        restaurants.Add(value);
    }

    // PUT: api/Restaurant/5
    public void Put([FromBody]Restaurant value)
    {
        restaurants.RemoveAll(r => r.Id == value.Id);
        restaurants.Add(value);
    }

    // DELETE: api/Restaurant/5
    public void Delete(int id)
    {
        restaurants.RemoveAll(r => r.Id == id);
    }
}

In the MVC Project

  • add a reference to the DTO Class Library Project
  • open the Package Manager Console and run the folowing command, to install the WebApiClient (for more details, see this and this):

Install-Package WebApiRestService.WebApiClient

  • create a controller called RestaurantsController, and paste this class:
C#
public class RestaurantsController : Controller
{
    private WebApiClientOptions options = 
                    new WebApiClientOptions("http://localhost:60214/api", "restaurant");

    public async Task<ActionResult> Index()
    {
        List<Restaurant> list = null;

        using(WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            list = await client.GetManyAsync();
        }

        return View(list);
    }

    public async Task<ActionResult> IndexOldFashioned()
    {
        List<Restaurant> list = null;

        HttpClient client = new HttpClient();
        client.BaseAddress = new Uri("http://localhost:60214/api/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
                                new MediaTypeWithQualityHeaderValue("application/json"));

        var response = await client.GetAsync("restaurant");

        if (!response.IsSuccessStatusCode)
        {
            return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); 
        }

        list = await response.Content.ReadAsAsync<List<Restaurant>>();
        
        return View("Index", list);
    }

    public async Task<ActionResult> Details(int? id)
    {
        Restaurant restaurant = null;

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(id);
        }
        
        if (restaurant == null)
        {
            return HttpNotFound();
        }
        
        return View(restaurant);
    }

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

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Create(Restaurant restaurant)
    {
        if (ModelState.IsValid)
        {
            using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
            {
                await client.CreateAsync(restaurant);
            }
            
            return RedirectToAction("Index");
        }

        return View(restaurant);
    }

    public async Task<ActionResult> Edit(int? id)
    {
        Restaurant restaurant = null;

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        
        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(id);
        }
        
        if (restaurant == null)
        {
            return HttpNotFound();
        }
        
        return View(restaurant);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(Restaurant restaurant)
    {
        if (ModelState.IsValid)
        {
            using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
            {
                await client.EditAsync(restaurant);
            }
            
            return RedirectToAction("Index");
        }
        
        return View(restaurant);
    }

    public async Task<ActionResult> Delete(int? id)
    {
        Restaurant restaurant = null;

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        
        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(id);
            
            if (restaurant == null)
            {
                return HttpNotFound();
            }
        }
        
        return View(restaurant);
    }

    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> DeleteConfirmed(Restaurant restaurant)
    {
        if (restaurant == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        using (WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
        {
            restaurant = await client.GetOneAsync(restaurant.Id);

            if (restaurant == null)
            {
                return HttpNotFound();
            }

            await client.DeleteAsync(restaurant.Id);
        }

        return RedirectToAction("Index");
    }
}

Now, you can run the MVC project, point to a URL like http://localhost:60232/restaurants/ and see the results.

As you can see in the above code, using the WebApiClient to call a RESTful service is pretty straight forward. All you need to do is create a WebApiClientOptions object, configure it as you like

C#
private WebApiClientOptions options = 
    new WebApiClientOptions("http://localhost:60214/api", "restaurant");

and start using the WebApiClient object to make calls to your service. Take a look at the Index action method:

C#
public async Task<ActionResult> Index()
{
    List<Restaurant> list = null;

    using(WebApiClient<Restaurant> client = new WebApiClient<Restaurant>(options))
    {
        list = await client.GetManyAsync();
    }

    return View(list);
}

If you have been using the the HttpClient so far, take a look at the next action method... you should be writing something like this:

C#
public async Task<ActionResult> IndexOldFashioned()
{
    List<Restaurant> list = null;

    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:60214/api/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new 
                         MediaTypeWithQualityHeaderValue("application/json"));

    var response = await client.GetAsync("restaurant");

    if (!response.IsSuccessStatusCode)
    {
        return new HttpStatusCodeResult(HttpStatusCode.InternalServerError); 
    }

    list = await response.Content.ReadAsAsync<List<Restaurant>>();
    
    return View("Index", list);
}

Now, if you compare these two different action methods you will probably see that the conventional method (using HttpClient) is much more difficult to read and maintain than that one using the WebApiClient. When you add more configuration like Authentication, the code becomes even more complex.

Other Features

The WebApiClient Library has a bunch of other features that will be covered in the next tutorials:

  • Authentication
  • Cookies
  • Inheritance
  • Exception Handling
  • Threads
  • Timeouts

 

 

 

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Brazil Brazil
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA13-Aug-14 3:24
professionalȘtefan-Mihai MOGA13-Aug-14 3:24 
GeneralRe: My vote of 5 Pin
Andreo Romera13-Aug-14 12:22
Andreo Romera13-Aug-14 12:22 
QuestionWhat's the difference from RestSharp? Pin
jwjosefy16-Jul-14 5:44
jwjosefy16-Jul-14 5:44 
AnswerRe: What's the difference from RestSharp? Pin
Andreo Romera17-Jul-14 6:26
Andreo Romera17-Jul-14 6:26 
AnswerVery useful! Pin
kutynko16-Jul-14 2:59
professionalkutynko16-Jul-14 2:59 
GeneralRe: Very useful! Pin
Andreo Romera17-Jul-14 6:20
Andreo Romera17-Jul-14 6:20 
QuestionSource code for the assembly? Pin
Ziad J.khan12-Jul-14 8:44
professionalZiad J.khan12-Jul-14 8:44 
AnswerRe: Source code for the assembly? Pin
Andreo Romera13-Jul-14 12:51
Andreo Romera13-Jul-14 12:51 
GeneralRe: Source code for the assembly? Pin
Ziad J.khan22-Jul-14 1:26
professionalZiad J.khan22-Jul-14 1:26 
GeneralRe: Source code for the assembly? Pin
Andreo Romera22-Jul-14 14:25
Andreo Romera22-Jul-14 14:25 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun10-Jul-14 0:39
Humayun Kabir Mamun10-Jul-14 0:39 
Generalthanks for… Pin
shenzhen led hero9-Jul-14 22:50
shenzhen led hero9-Jul-14 22:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.