2012-11-02 80 views
54

我創建了一個過去的一對夫婦的ASP.NET MVC應用程序,但我從來沒有使用過WebAPIs。我想知道我怎麼能創建一個簡單的MVC 4應用程序,通過的WebAPI,而不是通過正常的MVC控制器進行簡單的CRUD的東西。訣竅是,的WebAPI應該是一個獨立的解決方案(和,事實上,很可能是在不同的服務器/域)。ASP.NET MVC 4應用程序中調用遠程的WebAPI

我該怎麼做?我錯過了什麼?這只是一個設置路由指向WebAPI服務器的問題嗎?我發現展示瞭如何使用消費MVC應用程序WebAPIs所有的例子似乎承擔的WebAPI被「烤」到MVC應用程序,或者至少是在同一臺服務器上。

哦,爲了澄清,我不是在談論Ajax調用使用jQuery ......我的意思是MVC應用程序的控制器應使用的WebAPI獲取/放置數據。

回答

74

您應該使用新的HttpClient來消耗你的HTTP的API。我還可以建議你使你的調用完全異步。由於ASP.NET MVC控制器行動支持基於任務的異步編程模型,它是非常強大和方便。

下面是一個簡化的過於例子。下面的代碼是一個示例請求的輔助類:

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

然後,我可以異步消耗,通過我的MVC控制器如下:

public class HomeController : Controller { 

    private CarRESTService service = new CarRESTService(); 

    public async Task<ActionResult> Index() { 

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

你可以看看下面的帖子見異步I/O操作的ASP.NET MVC的影響:

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

+1

+1我在我的網絡應用程序中就像這樣做 –

+0

這看起來不錯,但我無法得到異步/等待的東西工作。 IDE不喜歡這些關鍵字。我正在使用.NET 4.0,並使用NuGet安裝了Web API客戶端庫。 –

+2

@GlennArndt除非你採取一些更多的行動,否則你不能在.NET 4.0中使用async/await。看到這篇博文:http://blogs.msdn.com/b/bclteam/archive/2012/10/22/using-async-await-without-net-framework-4-5.aspx您可以利用異步控制器操作沒有異步和等待關鍵字,但它會變得混亂。 – tugberk

1

http://restsharp.org/是回答你的問題。我目前正在將它用於具有相似結構的應用程序中。

但更普遍使用的WebAPI剛剛發佈,並請求數據如何處理是你的。你甚至可以使用標準的WebRequest和JavascriptSerializer。

乾杯。

+3

'WebRequest'和'JavascriptSerializer'現在是棧內的老派API。新的'HttpClient'是要走的路。它提供了OOTB格式支持,以及如果您安裝[Microsoft.AspNet.WebApi.Client](http://nuget.org/packages/Microsoft.AspNet.WebApi.Client)NuGet包,它將執行JSON序列化和反序列化使用Json.NET。 – tugberk

1

在這種情況下,你可以使用HttpClient從您的控制器使用Web API。

10

您可以使用WCF消費服務。像這樣:

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

然後你就可以在你的控制器使用它:

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

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

而且在你的web.config您將配置您的端點:

<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

我真的很喜歡用wcf來隱藏實現調用接口後面的服務的細節。非常好的提示。 – Martin

+0

我有一個ASP.net外部網站和一個MVC interal唯一的Web API。我怎樣才能做到這一點?從外部網站調用內部唯一的Web API? http://stackoverflow.com/questions/43002283/how-to-allow-internal-mvc-web-api-from-external-site-outside-the-network – Si8

15

謝謝大家爲答覆。我想,@ tugberk讓我走上了正確的道路。這個工作對我來說...

對於我CarsRESTService幫手:

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

然後換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

使用任何字符串插值(新的c#6功能添加,因爲這問題被問到)或string.builder而不是「string uri = baseUri + id;」,會使事情變得更容易閱讀,並且資源密集程度稍低:) – Rexxo

相關問題