2012-11-02 9 views
54

Ich habe ein paar ASP.NET MVC-Anwendungen in der Vergangenheit erstellt, aber ich habe noch nie zuvor WebAPIs verwendet. Ich frage mich, wie ich eine einfache MVC 4-App erstellen könnte, die einfache CRUD-Sachen über WebAPI statt über einen normalen MVC-Controller macht. Der Trick besteht darin, dass die WebAPI eine separate Lösung sein sollte (und tatsächlich auf einem anderen Server/einer anderen Domäne sein könnte).ASP.NET MVC 4 Anwendung Aufruf von Remote-WebAPI

Wie mache ich das? Was vermisse ich? Ist es nur eine Frage der Einrichtung von Routen, die auf den WebAPI-Server verweisen? Alle Beispiele, die ich gefunden habe, wie WebAPIs mit einer MVC-Anwendung konsumiert werden, scheinen anzunehmen, dass die WebAPI in die MVC-Anwendung "eingebacken" ist oder zumindest auf demselben Server ist.

Oh, und um zu verdeutlichen, ich spreche nicht über Ajax Anrufe mit jQuery ... Ich meine, dass der Controller der MVC-Anwendung die WebAPI verwenden sollte, um Daten zu bekommen/setzen.

Antwort

74

Sie sollten neue HttpClient verwenden, um Ihre HTTP-APIs zu verbrauchen. Was ich Ihnen zusätzlich raten kann, Ihre Anrufe komplett asynchron zu machen. Da ASP.NET MVC-Controller-Aktionen Task-based Asynchronous Programming-Modell unterstützen, ist es ziemlich mächtig und einfach.

Hier ist ein übermäßig vereinfachtes Beispiel. Der folgende Code ist die Hilfsklasse für eine Probe Anfrage:

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

Dann habe ich das durch meine MVC-Controller asynchron wie unten verbrauchen kann: zu

public class HomeController : Controller { 

    private CarRESTService service = new CarRESTService(); 

    public async Task<ActionResult> Index() { 

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

Sie haben einen Blick auf die unten Post sehen die Auswirkungen der asynchronen I/O-Operationen mit ASP.NET MVC:

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

+1

+1 Ich mache es genau so in meinen Web-Apps –

+0

Das sieht gut aus, aber ich kann die asynchronen/abwarten Sachen überhaupt nicht bekommen. Die IDE mag diese Schlüsselwörter nicht. Ich verwende .NET 4.0 und habe die Web-API-Client-Bibliotheken mit NuGet installiert. –

+2

@GlennArndt Sie können async/await mit .NET 4.0 nur verwenden, wenn Sie weitere Aktionen ausführen. Sehen Sie sich diesen Blog-Beitrag an: http://blogs.msdn.com/b/bclteam/archive/2012/10/22/using-async-await-without-net-framework-4-5.aspx Sie können asynchrone Controller-Aktionen nutzen ohne Async und warten auf Keywords, aber dann wird es chaotisch. – tugberk

1

http://restsharp.org/ ist die Antwort auf Ihre Fragen. Ich benutze es derzeit in einer Anwendung, die eine ähnliche Struktur hat.

Aber im Allgemeinen mit WebAPI ist nur Buchung und Anforderung von Daten, wie Sie zu verarbeiten ist an Ihnen. Sie können sogar Standard WebRequest und JavascriptSerializer verwenden.

Prost.

+3

'WebRequest' und' JavascriptSerializer' sind jetzt Old-School-APIs innerhalb des Stapels. Der neue 'HttpClient' ist weit weg. Es bietet auch Unterstützung für OOTB-Formatierung, wenn Sie das Paket [Microsoft.AspNet.WebApi.Client] (http://nuget.org/packages/Microsoft.AspNet.WebApi.Client) NuGet installieren und die Serialisierung und Deserialisierung von JSON durchführen mit Json.NET. – tugberk

1

In diesem Fall können Sie HttpClient verwenden, um Web-API von Ihrem Controller zu konsumieren.

10

Sie WCF verwenden, den Dienst zu verbrauchen. Wie 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(); 
    } 
} 

Und dann können Sie es in Ihrem Controller verbrauchen:

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

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

Und in Ihrer web.config legen Sie die Konfiguration für Ihren Endpunkt:

<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

Ich mag es wirklich, mit wcf die Implementierung zu verstecken Details zum Aufruf des Dienstes hinter einer Schnittstelle. Sehr guter Tipp. – Martin

+0

Ich habe eine externe ASP.net-Website und eine MVC Interal only Web API. Wie kann ich das Gleiche machen? Rufen Sie die interne Only Web API von der externen Site auf? http://stackoverflow.com/questions/43002283/how-to-allow-internal-mvc-web-api-from-external-site-outside-the-network – Si8

15

Vielen Dank allen für die Antworten. @tugberk hat mich auf den richtigen Weg gebracht, denke ich. Dieser arbeitete für mich ...

Für meine CarsRESTService Helfer:

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

Und dann für 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

Verwenden Sie entweder String-Interpolation (neue C# 6-Funktion seit diesem hinzugefügt Frage wurde gestellt) oder string.builder anstatt "string uri = baseUri + id;", wird die Dinge leichter zu lesen und etwas weniger ressourcenintensiv sein :) – Rexxo