2012-11-02 28 views
54

Ho creato un paio di applicazioni ASP.NET MVC in passato, ma non ho mai utilizzato WebAPI in precedenza. Mi chiedo come sia possibile creare una semplice app MVC 4 che esegua semplici operazioni CRUD tramite WebAPI anziché tramite un normale controller MVC. Il trucco è che WebAPI dovrebbe essere una soluzione separata (e, in effetti, potrebbe benissimo essere su un server/dominio diverso).ASP.NET MVC 4 Applicazione chiamata WebAPI remota

Come faccio? Cosa mi manca? Si tratta solo di impostare le rotte per puntare al server WebAPI? Tutti gli esempi che ho trovato che mostrano come utilizzare WebAPI utilizzando un'applicazione MVC sembrano presupporre che WebAPI sia "rodato" nell'applicazione MVC o almeno si trovi sullo stesso server.

Oh, e per chiarire, non sto parlando di chiamate Ajax utilizzando jQuery ... Voglio dire che il controller dell'applicazione MVC deve utilizzare WebAPI per ottenere/inserire dati.

risposta

74

È necessario utilizzare il nuovo HttpClient per utilizzare le API HTTP. Cosa posso inoltre consigliarti di effettuare chiamate completamente asincrone. Poiché le azioni del controller ASP.NET MVC supportano il modello di programmazione asincrona basata sulle attività, è piuttosto potente e facile.

Ecco un esempio semplificato. Il codice seguente è la classe helper per una richiesta di esempio:

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

Poi, posso consumare che, attraverso il mio controller MVC in modo asincrono, come di seguito:

public class HomeController : Controller { 

    private CarRESTService service = new CarRESTService(); 

    public async Task<ActionResult> Index() { 

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

Si può avere uno sguardo al post qui sotto per vedere gli effetti di operazioni di i/O asincrono con ASP.NET MVC:

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

+1

+1 Lo faccio esattamente nelle mie app web –

+0

Questo sembra fantastico, ma non riesco a far funzionare le cose asincrone/attese. L'IDE non ama quelle parole chiave. Sto usando .NET 4.0 e ho installato le librerie client API Web usando NuGet. –

+2

@GlennArndt Non è possibile utilizzare async/await con .NET 4.0 a meno che non si adottino ulteriori azioni. Vedi questo post del blog: http://blogs.msdn.com/b/bclteam/archive/2012/10/22/using-async-await-without-net-framework-4-5.aspx Puoi sfruttare le azioni del controller async w/o async e attendere le parole chiave ma poi diventa disordinato. – tugberk

1

http://restsharp.org/ è la risposta alle vostre domande. Attualmente sto usando in un'applicazione che ha una struttura simile.

Ma più in generale l'utilizzo di WebAPI è solo la pubblicazione e la richiesta dei dati su come elaborare dipende da voi. Puoi anche utilizzare WebRequest standard e JavascriptSerializer.

Cheers.

+3

'WebRequest' e' JavascriptSerializer' sono ora API vecchia scuola all'interno dello stack. Il nuovo 'HttpClient' è la strada da percorrere. Fornisce anche il supporto per la formattazione OOTB se si installa il pacchetto NuGet [Microsoft.AspNet.WebApi.Client] (http://nuget.org/packages/Microsoft.AspNet.WebApi.Client) e si eseguirà la serializzazione e deserializzazione JSON di usando Json.NET. – tugberk

1

In questo caso, è possibile utilizzare HttpClient per utilizzare Web API dal controller.

10

È possibile utilizzare WCF per utilizzare il servizio. In questo modo:

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

E allora si può consumare nel controller:

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

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

E nel tuo web.config si posiziona la configurazione per il punto finale:

<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

Mi piace molto usare wcf per nascondere l'implementazione dettagli su come chiamare il servizio dietro un'interfaccia. Un ottimo consiglio – Martin

+0

Possiedo un sito esterno ASP.net e un'API Web solo MVAL. Come posso fare lo stesso? Chiama l'API Web solo interna dal sito esterno? http://stackoverflow.com/questions/43002283/how-to-allow-internal-mvc-web-api-from-external-site-outside-the-network – Si8

15

Grazie a tutti per le risposte. @tugberk mi ha guidato lungo la strada giusta, penso. Questo ha funzionato per me ...

Per il mio CarsRESTService aiutante:

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

E poi per 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

Utilizzare l'interpolazione delle stringhe (aggiunta della nuova funzione # 6 aggiunta dal domanda è stata chiesta) o string.builder anziché "string uri = baseUri + id;", renderà le cose più facili da leggere e sarà leggermente meno dispendioso in termini di risorse :) – Rexxo

Problemi correlati