的WebAPI:反序列化的URI参数来波苏动作参数 [英] WebAPI: Deserialize URI parameter to poco action parameter

查看:165
本文介绍了的WebAPI:反序列化的URI参数来波苏动作参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于路由的定义是这样的:

  routes.MapHttpRoute(
            名字:分类,
            routeTemplate:{}控制器/分类/ {实体} / {}财产,
            默认:新{行动=类别,实体= RouteParameter.Optional,财产=姓名}
        );

,并宣布这样的控制器操作:

 公开的IEnumerable<类别及GT;分类(字符串属性);
公共IEnumerable的<类别及GT;分类(字符串实体,字符串属性);

的意图是,该控制器再present特定实体,并且它可以聚集等实体。返回的类别包含GROUPBY和财产计数。因此,如果控制器是UserController中,用户实体有一个Name属性,你可以调用用户/分类/名称和得到的结果显示出不同的名称以及有多少每个名字。

然而,如果一个用户也有一个地址实体,它有一个拉链code我可以打电话给用户/分类/地址/邮编code 和预计显示有多少用户住在什么邮编codeS。

结果

这里的问题是,字符串实体参数的类型是字符串,而不是键入键入,所以我脏了我的code动作将其转换为一个类型实例重新presenting实体,并抛出如果它是一个不正确的字符串。

我想是改为声明我这样的第二个动作:

 公开的IEnumerable<类别及GT;类别(类型实体,字符串属性);

但后来我需要反序列化使用自定义解串器的字符串。我有媒体链接又名 MediaTypeFormatters 的东西从身上内容正在添加自定义的解串器。这里我的问题是,在这种情况下,源是一个URI参数,而不是内容主体

这导致了我的问题:


  1. 将一个MediaTypeFormatter也为URI参数工作?

  2. 如果没有,什么结构必须实现我和挂钩如何实现我想要什么?


解决方案

东西夫妇:


  1. 用户/分类/名称不会图名为{}财产,它将匹配名称为{}实体。路由匹配贪婪地左到右。


  2. 而不是实体的字符串,你可以使用一个枚举

     公开枚举的EntityType
    {
        地址,
        部
    }公共类UserController的:ApiController
    {
        公共IEnumerable的<类别及GT;分类(的EntityType的实体,字符串属性)
        {
        }
    }

    您仍然需要code做的实体类型的东西,但似乎不是让客户给你随机CLR类型名称更安全?然后将模型绑定将验证URI中的{}实体段。所以,如果一个客户端请求用户/分类/ FavoriteBeer,他们将获得400错误的请求。


  3. 介质类型格式化是专为序列化/反序列化消息体。 (格式化程序映射到的介质类型,和媒体类型描述实体主体。)

    一个媒体类型格式化程序可以访问请求的URI,通过FormatterContext对象,但它不会帮助此方案,因为没有消息体的GET请求将不会调用格式化程序。


Given a route definition like this:

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

And a controller actions declared like this:

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

The intent is that the controller represent a specific entity, and it can aggregate other entities. The returned Categories contains a groupby and count of property. So if the controller is UserController and the user Entity has a Name property, you could call User/Categories/Name and get a result showing distinct names and how many have each name.

If however a User also have an Address entity, and it has a ZipCode I could call User/Categories/Address/ZipCode and expect a result showing how many Users live at what ZipCodes.

The problem here is that the string entity parameter is of type string rather than type Type, so I have to dirty up my action with code to convert this to a Type instance representing the Entity, and throwing if it is an incorrect string.

What I would like is to instead declare my second action like this:

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

But then I need to deserialize the string with a custom deserializer. I allready have custom deserializers aka MediaTypeFormatters for things comming from the content body. My problem here is that in this case the source is a URI parameter rather than the content body.

Which leads to my questions:

  1. Will a MediaTypeFormatter also work for URI parameters?
  2. If not, what construct must I implement and hook up how to achieve what I want?

解决方案

Couple of things:

  1. User/Categories/Name will not map "Name" to {property}, it will match "Name" to {entity}. Routes match "greedily" left-to-right.

  2. Instead of a string for entity, you could use an enum

    public enum EntityType
    {
        Address,
        Department
    }
    
    public class UserController : ApiController
    {
        public IEnumerable<Category> Categories(EntityType entity, string property)
        {
        }
    }
    

    You'll still need code to do something with the entity type, but that seems safer than letting the client send you random CLR type names? And then the model binding will validate the {entity} segment in the URI. So if a client requests User/Categories/FavoriteBeer, they will get 400, Bad Request.

  3. Media-type formatters are specifically for serializing/deserializing the message body. (Formatters map to media types, and media types describe the entity body.)

    A media-type formatter does have access to the request URI, through the FormatterContext object, but it won't help for this scenario, because a GET request with no message body will not invoke a formatter.

这篇关于的WebAPI:反序列化的URI参数来波苏动作参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆