WebAPI:将URI参数反序列化为poco动作参数

时间:2012-03-21 09:55:55

标签: c# .net url-routing asp.net-mvc-4 asp.net-web-api

给出这样的路线定义:

        routes.MapHttpRoute(
            name: "Categories",
            routeTemplate: "{controller}/Categories/{entity}/{property}",
            defaults: new { action = "Categories", entity = RouteParameter.Optional, property = "Name" }
        );

并且控制器动作声明如下:

public IEnumerable<Category> Categories(string property);
public IEnumerable<Category> Categories(string entity, string property);

意图是控制器代表一个特定的实体,它可以聚合其他实体。返回的Categories包含groupby和属性计数。因此,如果控制器是UserController并且用户实体具有Name属性,则可以调用User/Categories/Name并获得显示不同名称的结果以及每个名称的数量。

但是,如果用户也有一个地址实体,并且它有一个ZipCode,我可以调用User/Categories/Address/ZipCode并期望一个结果显示有多少用户生活在ZipCodes上。

这里的问题是string entity参数是string类型而不是类型Type,所以我必须用代码弄脏我的操作以将其转换为表示的Type实例实体,如果是不正确的字符串则抛出。

我想要的是宣布我的第二个动作:

public IEnumerable<Category> Categories(Type entity, string property);

但是我需要使用自定义反序列化器反序列化字符串。对于来自内容正文的内容,我已经有了自定义反序列化程序MediaTypeFormatters。我的问题是,在这种情况下,源是URI参数而不是内容体。

这引出了我的问题:

  1. MediaTypeFormatter是否也适用于URI参数?
  2. 如果没有,我必须实施什么构造,并勾勒出如何实现我的目标?

1 个答案:

答案 0 :(得分:3)

一些事情:

  1. 用户/类别/名称不会将“名称”映射到{property},它会将“名称”与{entity}匹配。路线从左到右“贪婪地”匹配。

  2. 您可以使用枚举

    代替实体字符串
    public enum EntityType
    {
        Address,
        Department
    }
    
    public class UserController : ApiController
    {
        public IEnumerable<Category> Categories(EntityType entity, string property)
        {
        }
    }
    

    您仍然需要使用代码对实体类型执行某些操作,但这似乎比让客户端发送随机CLR类型名称更安全吗?然后模型绑定将验证URI中的{entity}段。因此,如果客户端请求User / Categories / FavoriteBeer,他们将获得400,Bad Request。

  3. 媒体类型格式化程序专门用于序列化/反序列化邮件正文。 (格式化程序映射到媒体类型,媒体类型描述实体主体。)

    媒体类型格式化程序可以通过FormatterContext对象访问请求URI,但它对这种情况没有帮助,因为没有消息体的GET请求不会调用格式化程序。

    < / LI>