2012-11-02 12 views
54

Stworzyłem kilka aplikacji ASP.NET MVC w przeszłości, ale nigdy wcześniej nie korzystałem z WebAPI. Zastanawiam się, jak mogę stworzyć prostą aplikację MVC 4, która wykonuje proste rzeczy z CRUD przez WebAPI zamiast przez normalny kontroler MVC. Sztuczka polega na tym, że WebAPI powinien być osobnym rozwiązaniem (i, w rzeczywistości, może być na innym serwerze/domenie).ASP.NET MVC 4 Application Calling Remote WebAPI

Jak to zrobić? czego mi brakuje? Czy jest to tylko kwestia skonfigurowania tras do wskazania serwera WebAPI? Wszystkie przykłady, które znalazłem pokazujące, jak konsumować WebAPI za pomocą aplikacji MVC, wydają się zakładać, że WebAPI jest "upieczony" w aplikacji MVC lub przynajmniej jest na tym samym serwerze.

Aha, i aby wyjaśnić, nie mówię o wywołaniach Ajax za pomocą jQuery ... Mam na myśli to, że kontroler aplikacji MVC powinien używać WebAPI do pobierania/umieszczania danych.

Odpowiedz

74

Powinieneś używać nowego HttpClient do używania swoich API HTTP. Co mogę dodatkowo doradzić, aby połączenia były w pełni asynchroniczne. Ponieważ działania kontrolera ASP.NET MVC obsługują oparty na zadaniach model asynchronicznego programowania, jest on bardzo wydajny i łatwy.

Oto zbyt uproszczony przykład. Poniższy kod jest klasa pomocnika do wniosku próbki:

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)  
      ); 
     } 
    } 
} 

Następnie mogę konsumować, że dzięki moim kontroler MVC asynchronicznie jak poniżej:

public class HomeController : Controller { 

    private CarRESTService service = new CarRESTService(); 

    public async Task<ActionResult> Index() { 

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

Można rzucić okiem na poniższy pocztą zobaczyć efekty asynchronicznych operacji I/o z ASP.NET MVC:

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

+1

+1 Robię to dokładnie tak, jak w moich aplikacjach internetowych. –

+0

To wygląda świetnie, ale nie mogę uzyskać asynchronicznych/oczekujących rzeczy do pracy. IDE nie lubi tych słów kluczowych. Korzystam z .NET 4.0 i zainstalowałem biblioteki klienta Web API za pomocą NuGet. –

+2

@ GlennArndt Nie można używać async/await z .NET 4.0, chyba że wykonasz więcej akcji. Zobacz ten post na blogu: http://blogs.msdn.com/b/bclteam/archive/2012/10/22/using-async-await-without-net-framework-4-5.aspx Możesz wykorzystać akcje kontrolera asynchronicznego bez asynchronizacji i czekam na słowa kluczowe, ale potem robi się bałagan. – tugberk

1

http://restsharp.org/ jest odpowiedzią na twoje pytania. Obecnie używam go w aplikacji o podobnej strukturze.

Jednak ogólnie mówiąc, korzystanie z WebAPI polega na publikowaniu i żądanie danych, które należy wykonać, zależy od Ciebie. Możesz nawet użyć standardowego WebRequest i JavascriptSerializer.

Pozdrawiam.

+3

'WebRequest' i' JavascriptSerializer' są teraz oldschoolowymi interfejsami API wewnątrz stosu. Nowy 'HttpClient' jest na dobrej drodze. Zapewnia obsługę formatowania OOTB również po zainstalowaniu pakietu [Microsoft.AspNet.WebApi.Client] (http://nuget.org/packages/Microsoft.AspNet.WebApi.Client) NuGet i przeprowadzi serializację i deserializację JSON przez przy użyciu Json.NET. – tugberk

1

W tym przypadku możesz użyć interfejsu WWW API ze swojego kontrolera, używając HttpClient.

10

można użyć WCF konsumować usługę. Tak:

[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(); 
    } 
} 

a następnie można je spożywać w kontrolerze:

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

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

I w web.config umieścić konfigurację do końcowego:

<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> 
+0

Naprawdę lubię używać wcf, aby ukryć implementację szczegóły wywoływania usługi za interfejsem. Bardzo dobra wskazówka. – Martin

+0

Mam zewnętrzną witrynę ASP.net i internetowe API MVC. Jak mogę zrobić to samo? Zadzwoń do wewnętrznego interfejsu API wyłącznie z zewnętrznej strony? http://stackoverflow.com/questions/43002283/how-to-allow-internal-mvc-web-api-od-external-site-outside-the-network – Si8

15

Dzięki wszystkim dla odpowiedzi. @tugberk prowadził mnie właściwą ścieżką, tak myślę. Ten pracował dla mnie ...

Dla mojego CarsRESTService pomocnika:

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; 
     } 
    } 
} 

a następnie przez 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); 
    } 
} 
+0

Użyj interpolacji napisów (nowa funkcja C# 6 dodana od tego pytanie zostało zadane) lub string.builder zamiast "string uri = baseUri + id;", sprawi, że rzeczy będą łatwiejsze do odczytania i będą nieco mniej wymagające zasobów :) – Rexxo

Powiązane problemy