给出这样的路线定义:
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参数而不是内容体。
这引出了我的问题:
答案 0 :(得分:3)
一些事情:
用户/类别/名称不会将“名称”映射到{property},它会将“名称”与{entity}匹配。路线从左到右“贪婪地”匹配。
您可以使用枚举
代替实体字符串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。
媒体类型格式化程序专门用于序列化/反序列化邮件正文。 (格式化程序映射到媒体类型,媒体类型描述实体主体。)
媒体类型格式化程序可以通过FormatterContext对象访问请求URI,但它对这种情况没有帮助,因为没有消息体的GET请求不会调用格式化程序。
< / LI> 醇>