61

I've created a couple ASP.NET MVC applications in the past, but I've never used WebAPIs before. I'm wondering how I could create a simple MVC 4 app that does simple CRUD stuff via WebAPI instead of through a normal MVC controller. The trick is that the WebAPI should be a separate solution (and, in fact, could very well be on a different server/domain).

How do I do that? What am I missing? Is it just a matter of setting up routes to point to the WebAPI's server? All the examples I've found showing how to consume WebAPIs using an MVC application seem to assume the WebAPI is "baked in" to the MVC application, or at least is on the same server.

Oh, and to clarify, I'm not talking about Ajax calls using jQuery... I mean that the MVC application's controller should use the WebAPI to get/put data.

5 Answers 5

81

You should use new HttpClient to consume your HTTP APIs. What I can additionally advise you to make your calls fully asynchronous. As ASP.NET MVC controller actions support Task-based Asynchronous Programming model, it is pretty powerful and easy.

Here is an overly simplified example. The following code is the helper class for a sample request:

public class CarRESTService {

    readonly string uri = "http://localhost:2236/api/cars";

    public async Task<List<Car>> GetCarsAsync() {

        using (HttpClient httpClient = new HttpClient()) {

            return JsonConvert.DeserializeObject<List<Car>>(
                await httpClient.GetStringAsync(uri)    
            );
        }
    }
}

Then, I can consume that through my MVC controller asynchronously as below:

public class HomeController : Controller {

    private CarRESTService service = new CarRESTService();

    public async Task<ActionResult> Index() {

        return View("index",
            await service.GetCarsAsync()
        );
    }
}

You can have a look at the below post to see the effects of asynchronous I/O operations with ASP.NET MVC:

My Take on Task-based Asynchronous Programming in C# 5.0 and ASP.NET MVC Web Applications

Sign up to request clarification or add additional context in comments.

7 Comments

This looks great, but I can't get the async/await stuff to work at all. The IDE doesn't like those keywords. I'm using .NET 4.0 and have installed the Web API client libraries using NuGet.
@GlennArndt You cannot use async/await with .NET 4.0 unless u take some more actions. See this blog post: blogs.msdn.com/b/bclteam/archive/2012/10/22/… You can leverage async controller actions w/o async and await keywords but then it gets messy.
I know its an old post but I am not been able to find the answer. Question is in the above solution code how would you do a httppost with Request Body with json data?
@tugberk what if I want to get the url: localhost:2236 automatically in mvc, is there a way to get it ?
This might be the best method for consuming a custom web API from .NET that I've found so far. I like it. Nicely done, @tugberk
|
18

Thanks everyone for the responses. @tugberk led me down the right path, I think. This worked for me...

For my CarsRESTService helper:

public class CarsRESTService
{
    readonly string baseUri = "http://localhost:9661/api/cars/";

    public List<Car> GetCars()
    {
        string uri = baseUri;
        using (HttpClient httpClient = new HttpClient())
        {
            Task<String> response = httpClient.GetStringAsync(uri);
            return JsonConvert.DeserializeObjectAsync<List<Car>>(response.Result).Result;
        }
    }

    public Car GetCarById(int id)
    {
        string uri = baseUri + id;
        using (HttpClient httpClient = new HttpClient())
        {
            Task<String> response = httpClient.GetStringAsync(uri);
            return JsonConvert.DeserializeObjectAsync<Car>(response.Result).Result;
        }
    }
}

And then for CarsController.cs:

public class CarsController : Controller
{
    private CarsRESTService carsService = new CarsRESTService();

    //
    // GET: /Cars/

    public ActionResult Index()
    {
        return View(carsService.GetCars());
    }

    //
    // GET: /Cars/Details/5

    public ActionResult Details(int id = 0)
    {
        Car car = carsService.GetCarById(id);

        if (car == null)
        {
            return HttpNotFound();
        }
        return View(car);
    }
}

1 Comment

Use either string interpolation (new c# 6 feature added since this question was asked) or string.builder rather than "string uri = baseUri + id;", will make things easier to read and be slightly less resource intensive :)
10

You can use WCF to consume the service. Like so:

[ServiceContract]
public interface IDogService
{
    [OperationContract]
    [WebGet(UriTemplate = "/api/dog")]
    IEnumerable<Dog> List();
}

public class DogServiceClient : ClientBase<IDogService>, IDogService
{
    public DogServiceClient(string endpointConfigurationName) : base(endpointConfigurationName)
    {
    }

    public IEnumerable<Dog> List()
    {
        return Channel.List();
    }
}

And then you can consume it in your controller:

public class HomeController : Controller
{
    public HomeController()
    {
    }

    public ActionResult List()
    {
        var service = new DogServiceClient("YourEndpoint");
        var dogs = service.List();
        return View(dogs);
    }
}

And in your web.config you place the configuration for your endpoint:

<system.serviceModel>
  <client>
    <endpoint address="http://localhost/DogService" binding="webHttpBinding"
    bindingConfiguration="" behaviorConfiguration="DogServiceConfig" 
    contract="IDogService" name="YourEndpoint" />
  </client>
  <behaviors>
    <endpointBehaviors>
      <behavior name="DogServiceConfig">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

2 Comments

I really like using wcf to hide the implementation details of calling the service behind an interface. Very good tip.
I have an ASP.net external site and a MVC interal only Web API. How can I do the same? Call the internal only Web API from the external site? stackoverflow.com/questions/43002283/…
1

http://restsharp.org/ is the answer to your questions. I am currently using it in an application which has similar structure.

But more generally using WebAPI is just posting and requesting data how to process is up to you. You can even use standard WebRequest and JavascriptSerializer.

Cheers.

1 Comment

WebRequest and JavascriptSerializer are now old-school APIs inside the stack. The new HttpClient is way to go. It provides OOTB formatting support as well if you install Microsoft.AspNet.WebApi.Client NuGet package and it will perform the JSON serialization and deserialization by using Json.NET.
1

In this case, you can use HttpClient to consume Web API from your controller.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.