测试以对象作为参数的GET请求(Asp.NET WebApi控制器)

时间:2013-08-29 14:29:52

标签: c# asp.net asp.net-web-api

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

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

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

编辑:感谢大家的反馈,我的问题的解决方案实际上比我预期的要容易得多。我绝对喜欢向你们所有人投票,虽然不幸的是我的声誉太低了(我是stackoverflow的新手),所以我不得不在不久的将来回到这一点。干杯:)

2 个答案:

答案 0 :(得分:19)

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

例如:

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

你的控制器方法就是这个

GetAllItems(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; carrier.Name =“ABC”

答案 1 :(得分: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返回项目列表的动作,这在概念上可能更好,但路由原理是相同的。