2012-11-02 79 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

相关问题