Click here to Skip to main content
14,604,663 members

Calling a RESTful Service like ASP.NET WebApi using WebApiClient

Rate this:
4.78 (11 votes)
Please Sign up or sign in to vote.
4.78 (11 votes)
9 Jul 2014CPOL
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:
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:
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:
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

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:

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:

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)

Share

About the Author

Andreo Romera
Software Developer (Senior)
Brazil Brazil
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 Pin
Ștefan-Mihai MOGA13-Aug-14 3:24
professionalȘtefan-Mihai MOGA13-Aug-14 3:24 
This is a great inspiring article. I am pretty much pleased with your good work. You put really very helpful information. Keep it up once again.
GeneralRe: My vote of 5 Pin
Andreo Romera13-Aug-14 12:22
MemberAndreo Romera13-Aug-14 12:22 
QuestionWhat's the difference from RestSharp? Pin
jwjosefy16-Jul-14 5:44
Memberjwjosefy16-Jul-14 5:44 
AnswerRe: What's the difference from RestSharp? Pin
Andreo Romera17-Jul-14 6:26
MemberAndreo Romera17-Jul-14 6:26 
AnswerVery useful! Pin
kutynko16-Jul-14 2:59
Memberkutynko16-Jul-14 2:59 
GeneralRe: Very useful! Pin
Andreo Romera17-Jul-14 6:20
MemberAndreo 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
MemberAndreo 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
MemberAndreo Romera22-Jul-14 14:25 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun10-Jul-14 0:39
MemberHumayun Kabir Mamun10-Jul-14 0:39 
Generalthanks for… Pin
shenzhen led hero9-Jul-14 22:50
Membershenzhen 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.

Article
Posted 9 Jul 2014

Stats

32K views
482 downloads
37 bookmarked