12

我被指派为应用程序开发 WebAPI 控制器(我以前从未使用过的东西)。一切都很顺利,有一些基本的请求,比如 GetAllUsers(int id) 只是出于测试原因 - 配置本身很好。

现在问题来了。我有一个方法 GetAllItems(Carrier carrier),其中 Carrier 是一个具有许多不同参数的类。由于我们已经在数据库中有几个 Carrier 实例用于测试目的,我尝试的是查询数据库,根据 ID (GUID) 属性选择 Carrier 的实例,但没有结果。

当输入参数是一个对象而不是单个值(例如 int ID)时,有没有办法使用测试方法或某种测试输入参数手动测试 GET 请求?

编辑:感谢大家的反馈,我的问题的解决方案实际上比我预期的要容易得多。我绝对愿意为你们所有人投票,尽管不幸的是我的声誉太低而不能这样做(我是 stackoverflow 的新手),所以我必须在不久的将来的某个时候重新这样做。干杯:)

4

2 回答 2

20

据我了解您的问题,您希望能够直接在 URL 中而不是在您的请求正文中传递运营商的属性。

前任:

[GET] http://localhost/entities?id=000000000000000

你的控制器方法是这个

GetAllItems(Carrier carrier)

Carrier 有一个 Id (Guid) 属性:

class Carrier {
    public Guid Id { get; set; }
    public string Name { get; set; }
}

Carrier 在 WebApi 模型绑定方面是一个复杂的对象。

模型绑定的默认行为是:

默认情况下,Web API 使用以下规则绑定参数: 如果参数是“简单”类型,Web API 会尝试从 URI 中获取值。简单类型包括 .NET 基本类型(int、bool、double 等),加上 TimeSpan、DateTime、Guid、decimal 和 string,以及任何具有可以从字符串转换的类型转换器的类型。(稍后将详细介绍类型转换器。)对于复杂类型,Web API 尝试使用媒体类型格式化程序从消息正文中读取值。

见:http ://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

期望与 URL 中的复杂对象绑定的模型不是 WebApi 默认行为。

如果您希望您的控制器方法从 URL 模型绑定一个复杂对象,您必须告诉它。

GetAllItems([FromUri] Carrier carrier)

使用 FromUri 绑定指示器,您可以使用来自 URL 的复杂模型绑定

现在您甚至可以在 URL 中添加更多属性映射:

[GET] http://localhost/entities?id=000000000000000&name=ABC

GetAllItems 将收到一个 Carrier 对象,其中填充了:carrier.Id = 0000-00000000000-000; 运营商名称 = "ABC"

于 2013-08-29T19:05:48.680 回答
4

您在这里遇到了路由问题以及一些误解。

WebApi 的默认路由是:

routes.MapHttpRoute(
            name: "Default",
            routeTemplate: "{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

这与某些约定一起:

  • GetX 映射 GET 方法。
  • InsertX 映射 POST 方法。
  • UpdateX 映射 PUT 方法。
  • DeleteX 映射 DELETE 方法。

当您的命名约定与 WepApi 约定不一致时,您需要指定方法、操作名称等。

您的路线也会发生同样的情况。如果您没有定义其他路由,则只有遵循约定和默认路由的操作才会受到限制。

例如:

public IEnumerable<Carrier> GetAll(){
   //this will get called when using the route: /api/carriers/
}

public IEnumerable<Carrier> Get(string id){
   //this will be called when using the route: /api/carriers/1
   //where 1 is the carrier id
}

将在 CarrierController 中工作,因为它们都符合约定和路线。

现在,如果您需要一个为承运人返回所有物品的方法,您将需要此方法:

[ActionName("getItems")]
public IEnumerable<Item> GetAllItems(string id){
   //where id is the carrierid       
   var carrierId = id;
   //because you are specifying the ActionName to getItems this will match the following route: 
   // /api/carriers/getItems/1
}

另一种选择是创建一个 ItemsController,并添加一个基于 carrierId 返回项目列表的操作,这在概念上可能更好,但路由原理是相同的。

于 2013-08-29T14:57:43.617 回答