人为设置让web api参数反序列化为json

潮起潮落 2013-12-18 08:16:18
webapi的参数反序列化是根据HTTP请求中的Content-type
现在有这样一个场景
在发起HTTP请求都时候,ContentType不填或者随意填,Action内接收的参数按照json格式反序列化

思路1.
通过某种方式在参数序列化之前改变HTTP请求的ContentType,或者让web api进行参数反序列化的时候读取的ContentType为我们想要的值。
比如在请求的时候填写Content-Type:text/plain
然后经过某种处理,在webapi进行反序列化的时候他读到的Content-Type:application/json。
然后他按照json格式去处理

思路2.
设定类似于Content-Type填写application/json映射参数使用json反序列化这样的映射,比如我在url中写type=json,即可映射为使用json格式反序列化参数。
通过以下这种方式似乎是配置返回值的序列化方式的,并不影响接收参数的反序列化。

QueryStringMapping jsonMapping = new QueryStringMapping("type", "json", "application/json");
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);


这两种哪一种可以行得通呢,或者有更好的解决办法解决这个问题。
求解惑。

上个帖子中有朋友提到在filter判定,但是并不好使。。因为使用actionContext.ActionArguments;都可以获取到反序列化的参数了- - 再去设置headers也无甚意义吧。
...全文
449 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
潮起潮落 2013-12-19
  • 打赏
  • 举报
回复
引用 12 楼 KarasCanvas 的回复:


public MediaTypeFormatter FindReader(Type type, MediaTypeHeaderValue mediaType)
{
    if (type == null)
    {
        throw Error.ArgumentNull("type");
    }
    if (mediaType == null)
    {
        throw Error.ArgumentNull("mediaType");
    }
    foreach (MediaTypeFormatter formatter in base.Items)
    {
        if ((formatter != null) && formatter.CanReadType(type))
        {
            foreach (MediaTypeHeaderValue value2 in formatter.SupportedMediaTypes)
            {
                if ((value2 != null) && value2.IsSubsetOf(mediaType))
                {
                    return formatter;
                }
            }
            continue;
        }
    }
    return null;
}

去翻了下源代码,这应该是查找反序列化用的formatter的方法 可以通过设置 //var f = config.Formatters.JsonFormatter; //f.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("mimetype")); 让JsonFormatter支持其他contentype..但是不能用空值..
同去看了一下web api的代码,也没找着门路。 最终通过自定义的HttpParameterBinding结合目标实体都继承于某个接口(不一定非得是这样,拥有同样的Attribute,继承于同一个父类都行,只是标识一下)解决了。 绕了一大圈还是回到最开始的地方,总觉得不够优雅。为啥不能像返回值那样一两代码配置呢。 测试项目地址:http://pan.baidu.com/s/1qxSoA 明天晚上如果没有更好的解决办法就结贴了。。
种草德鲁伊 2013-12-18
  • 打赏
  • 举报
回复


public MediaTypeFormatter FindReader(Type type, MediaTypeHeaderValue mediaType)
{
    if (type == null)
    {
        throw Error.ArgumentNull("type");
    }
    if (mediaType == null)
    {
        throw Error.ArgumentNull("mediaType");
    }
    foreach (MediaTypeFormatter formatter in base.Items)
    {
        if ((formatter != null) && formatter.CanReadType(type))
        {
            foreach (MediaTypeHeaderValue value2 in formatter.SupportedMediaTypes)
            {
                if ((value2 != null) && value2.IsSubsetOf(mediaType))
                {
                    return formatter;
                }
            }
            continue;
        }
    }
    return null;
}

去翻了下源代码,这应该是查找反序列化用的formatter的方法 可以通过设置 //var f = config.Formatters.JsonFormatter; //f.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("mimetype")); 让JsonFormatter支持其他contentype..但是不能用空值..
潮起潮落 2013-12-18
  • 打赏
  • 举报
回复
引用 10 楼 KarasCanvas 的回复:
web api真没用过,如果不能通过配置的话,我觉得可以考虑从ModelBinding入手
那可能是我想得简单了? 因为左右返回值的序列化方式是那么地方便,不禁去想是不是有我不知道的、简便的方式去配置参数的反序列化方式。。
种草德鲁伊 2013-12-18
  • 打赏
  • 举报
回复
web api真没用过,如果不能通过配置的话,我觉得可以考虑从ModelBinding入手
潮起潮落 2013-12-18
  • 打赏
  • 举报
回复
引用 7 楼 KarasCanvas 的回复:
[quote=引用 4 楼 KongHuLu 的回复:] 单独项目下载 如下形式的代码,是可以实现custom为test1时返回json类型的数据,csutom为test2的时候返回xml类型的数据。 但是对参数的反序列化毫无影响。

MediaTypeMapping jsonMapping = new RequestHeaderMapping("custom", "test1", StringComparison.CurrentCultureIgnoreCase, true, "application/json");
            config.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);
            MediaTypeMapping xmlMapping = new RequestHeaderMapping("custom", "test2", StringComparison.CurrentCultureIgnoreCase, true, "application/xml");
            config.Formatters.XmlFormatter.MediaTypeMappings.Add(xmlMapping);
原来楼主思路2是没实现的啊,看走眼了[/quote] 嗯。。“通过以下这种方式似乎是配置返回值的序列化方式的,并不影响接收参数的反序列化。” 是说找到一种方式如下配置,像左右返回值序列化方式一样左右参数反序列化方式。
潮起潮落 2013-12-18
  • 打赏
  • 举报
回复
引用 6 楼 wanghui0380 的回复:
啥也别说了,直接上官方的说明 http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
恕我愚钝,没有看到帖子提及问题的解决途径。。
种草德鲁伊 2013-12-18
  • 打赏
  • 举报
回复
引用 4 楼 KongHuLu 的回复:
单独项目下载 如下形式的代码,是可以实现custom为test1时返回json类型的数据,csutom为test2的时候返回xml类型的数据。 但是对参数的反序列化毫无影响。

MediaTypeMapping jsonMapping = new RequestHeaderMapping("custom", "test1", StringComparison.CurrentCultureIgnoreCase, true, "application/json");
            config.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);
            MediaTypeMapping xmlMapping = new RequestHeaderMapping("custom", "test2", StringComparison.CurrentCultureIgnoreCase, true, "application/xml");
            config.Formatters.XmlFormatter.MediaTypeMappings.Add(xmlMapping);
原来楼主思路2是没实现的啊,看走眼了
wanghui0380 2013-12-18
  • 打赏
  • 举报
回复
啥也别说了,直接上官方的说明 http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
潮起潮落 2013-12-18
  • 打赏
  • 举报
回复
引用 4 楼 KongHuLu 的回复:
单独项目下载 如下形式的代码,是可以实现custom为test1时返回json类型的数据,csutom为test2的时候返回xml类型的数据。 但是对参数的反序列化毫无影响。

MediaTypeMapping jsonMapping = new RequestHeaderMapping("custom", "test1", StringComparison.CurrentCultureIgnoreCase, true, "application/json");
            config.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);
            MediaTypeMapping xmlMapping = new RequestHeaderMapping("custom", "test2", StringComparison.CurrentCultureIgnoreCase, true, "application/xml");
            config.Formatters.XmlFormatter.MediaTypeMappings.Add(xmlMapping);
下载地址:http://pan.baidu.com/s/1mufYY
潮起潮落 2013-12-18
  • 打赏
  • 举报
回复
单独项目下载 如下形式的代码,是可以实现custom为test1时返回json类型的数据,csutom为test2的时候返回xml类型的数据。 但是对参数的反序列化毫无影响。

MediaTypeMapping jsonMapping = new RequestHeaderMapping("custom", "test1", StringComparison.CurrentCultureIgnoreCase, true, "application/json");
            config.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);
            MediaTypeMapping xmlMapping = new RequestHeaderMapping("custom", "test2", StringComparison.CurrentCultureIgnoreCase, true, "application/xml");
            config.Formatters.XmlFormatter.MediaTypeMappings.Add(xmlMapping);
潮起潮落 2013-12-18
  • 打赏
  • 举报
回复
引用 2 楼 KarasCanvas 的回复:
而且MediaTypeMapping还是个抽象类,可以自己实现匹配关系..

感觉MediaTypeMapping也是设置返回值序列化的

Application_Start中设置

MediaTypeMapping jsonMapping = new RequestHeaderMapping("custom","test", StringComparison.CurrentCultureIgnoreCase,true,"application/json");
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);


Fiddler2中传输:

程序中接收可以看到有custom:test这个header

但是参数answer依然为null

Answer类型为:

public class Answer
{
/// <summary>
/// 获取或设置 答案ID
/// </summary>
[Description("答案id")]
public int AID { get; set; }
/// <summary>
/// 获取或设置 问题ID
/// </summary>
[Description("问题id")]
public int QID { get; set; }
/// <summary>
/// 获取或设置 答案
/// </summary>
[Description("答案")]
public string AnswerContent { get; set; }
/// <summary>
/// 获取或设置 问题类型ID
/// </summary>
[Description("问题类型id")]
public int QTID { get; set; }
/// <summary>
/// 获取或设置 题组ID
/// </summary>
[Description("题组id")]
public int QGID { get; set; }

}


这是在我自己的项目中测试的,等下我单独建个新项目进行测试,不行的话就把程序包发出来。

望指点。
种草德鲁伊 2013-12-18
  • 打赏
  • 举报
回复
而且MediaTypeMapping还是个抽象类,可以自己实现匹配关系..
种草德鲁伊 2013-12-18
  • 打赏
  • 举报
回复
为啥不用RequestHeaderMapping呢

62,199

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧