web api 参数绑定

简单类型参数: url读取(string,bool,int...)

复杂类型参数:从message body用media-type formatter 读取

url读取route data(路由解析uri的时候得到)和URI query string

强制复杂类型从uri获取

public class GeoPoint
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

public ValuesController : ApiController
{
    public HttpResponseMessage Get([FromUri] GeoPoint location) { ... }
}

http://localhost/api/values/?Latitude=47.678558&Longitude=-122.130989

强制简单类型从request body获取([FromBody]时webapi 会用Content-Type选择一个media type formatter)

public HttpResponseMessage Post([FromBody] string name) { ... } //只能用于一个参数的情况

POST http://localhost:5076/api/values HTTP/1.1User-Agent: FiddlerHost: localhost:5076Content-Type: application/jsonContent-Length: 7

"Alice"

类型转换(实现类型转换后,会当做简单类型尝试从uri获取)

[TypeConverter(typeof(GeoPointConverter))]
public class GeoPoint
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }

    public static bool TryParse(string s, out GeoPoint result)
    {
        result = null;

        var parts = s.Split(‘,‘);
        if (parts.Length != 2)
        {
            return false;
        }

        double latitude, longitude;
        if (double.TryParse(parts[0], out latitude) &&
            double.TryParse(parts[1], out longitude))
        {
            result = new GeoPoint() { Longitude = longitude, Latitude = latitude };
            return true;
        }
        return false;
    }
}

class GeoPointConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context,
        CultureInfo culture, object value)
    {
        if (value is string)
        {
            GeoPoint point;
            if (GeoPoint.TryParse((string)value, out point))
            {
                return point;
            }
        }
        return base.ConvertFrom(context, culture, value);
    }
}

public HttpResponseMessage Get(GeoPoint location) { ... }

http://localhost/api/values/?location=47.678558,-122.130989

Model Binders

public class GeoPointModelBinder : IModelBinder
{
    // List of known locations.
    private static ConcurrentDictionary<string, GeoPoint> _locations
        = new ConcurrentDictionary<string, GeoPoint>(StringComparer.OrdinalIgnoreCase);

    static GeoPointModelBinder()
    {
        _locations["redmond"] = new GeoPoint() { Latitude = 47.67856, Longitude = -122.131 };
        _locations["paris"] = new GeoPoint() { Latitude = 48.856930, Longitude = 2.3412 };
        _locations["tokyo"] = new GeoPoint() { Latitude = 35.683208, Longitude = 139.80894 };
    }

    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(GeoPoint))
        {
            return false;
        }

        ValueProviderResult val = bindingContext.ValueProvider.GetValue(
            bindingContext.ModelName);
        if (val == null)
        {
            return false;
        }

        string key = val.RawValue as string;
        if (key == null)
        {
            bindingContext.ModelState.AddModelError(
                bindingContext.ModelName, "Wrong value type");
            return false;
        }

        GeoPoint result;
        if (_locations.TryGetValue(key, out result) || GeoPoint.TryParse(key, out result))
        {
            bindingContext.Model = result;
            return true;
        }

        bindingContext.ModelState.AddModelError(
            bindingContext.ModelName, "Cannot convert value to Location");
        return false;
    }
}

使用

//1
public HttpResponseMessage Get([ModelBinder(typeof(GeoPointModelBinder))] GeoPoint location)

//2
[ModelBinder(typeof(GeoPointModelBinder))]
public class GeoPoint
{
    // ....
}

//3
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var provider = new SimpleModelBinderProvider(
            typeof(GeoPoint), new GeoPointModelBinder());
        config.Services.Insert(typeof(ModelBinderProvider), 0, provider);

        // ...
    }
}
public HttpResponseMessage Get([ModelBinder] GeoPoint location) { ... }

value provider(解析参数返回字典对象)

例:

http://localhost/api/values/1?location=48,-122

会解析为字典

  • id = "1"
  • location = "48,122"

id,location对应ModelBindingContext.ModelName

"1","48,122" RawValue如果被正确转换会被设置到ModelBindingContext.Model

public class CookieValueProvider : IValueProvider
{
    private Dictionary<string, string> _values;

    public CookieValueProvider(HttpActionContext actionContext)
    {
        if (actionContext == null)
        {
            throw new ArgumentNullException("actionContext");
        }

        _values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        foreach (var cookie in actionContext.Request.Headers.GetCookies())
        {
            foreach (CookieState state in cookie.Cookies)
            {
                _values[state.Name] = state.Value;
            }
        }
    }

    public bool ContainsPrefix(string prefix)
    {
        return _values.Keys.Contains(prefix);
    }

    public ValueProviderResult GetValue(string key)
    {
        string value;
        if (_values.TryGetValue(key, out value))
        {
            return new ValueProviderResult(value, value, CultureInfo.InvariantCulture);
        }
        return null;
    }
}

使用(查找值时会使用所有注册的value provider查找,得到第一个返回的值)

public class CookieValueProviderFactory : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(HttpActionContext actionContext)
    {
        return new CookieValueProvider(actionContext);
    }
}

public static void Register(HttpConfiguration config)
{
    config.Services.Add(typeof(ValueProviderFactory), new CookieValueProviderFactory());

    // ...
}

// 不使用其他value provider
public HttpResponseMessage Get(
    [ValueProvider(typeof(CookieValueProviderFactory))] GeoPoint location)

HttpParameterBinding

url:http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

时间: 2024-10-05 15:31:19

web api 参数绑定的相关文章

细说 Web API参数绑定和模型绑定

今天跟大家分享下在Asp.NET Web API中Controller是如何解析从客户端传递过来的数据,然后赋值给Controller的参数的,也就是参数绑定和模型绑定. Web API参数绑定就是简单类型的绑定,比如:string,char,bool,int,uint,byte,sbyte,short,ushort,long, float这些基元类型.模型绑定就是除此之外的复杂类型的绑定.大家都知道在MVC中模型绑定都是通过默认的DefaultModelBinder来绑定的,没有Get请求和P

asp.net web api参数

翻译自:http://www.c-sharpcorner.com/article/parameter-binding-in-asp-net-web-api/ 主要自己学习下,说是翻译,主要是把文章的意思记录下,下面进入正题 web api 对于一般的基本类型(primitive type)(bool,int ,double,log,timespan,datetime,guid,string)直接从url读取,对于复杂类型,web api从请求的body获取,需要使用media type. 对于这

Web Api 模型绑定 一

[https://docs.microsoft.com/zh-cn/aspnet/core/web-api/?view=aspnetcore-2.2] 1.模型绑定 简单模型绑定针对简单类型(如string,int,DateTime等)可进行单一绑定:但若遇到复杂类型,则需要通过反射和递归遍历查找,查找模式paramter_name.property_name. >>> 对于Collection类型,模型查找将查找parameter_name[index]或[index]的匹配项 >

ASP.Net Web API 的参数绑定[翻译]

原文地址:Parameter Binding in ASP.NET Web API 译文如下: 当Web API相应Controller的一个方法时,它必定存在一个设置参数的过程,叫作数据绑定.这篇文章描述了Web API如何绑定参数以及如何自定义绑定过程. 一般情况下,Web API绑定参数符合如下规则: 如果参数为简单类型,Web API 尝试从URI中获取.简单参数类型包含.Net源生类型(int,bool,double...),加上TimeSpan,DateTime,Guid,decim

基于.Net Framework 4.0 Web API开发(2):ASP.NET Web APIs 参数传递方式详解

概述:  ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.调用API过程中参数的传递是必须的,本节就来谈谈API使用过程中参数的传递方式. 各种参数传递方式的实现: ASP.NET Web API参数有两种传递方式,一种是请求时携带QueryString,对应API 开发中的FromUrlAttribute属性,也是参数传递默认属性,并且每个API可以含有多个此类型的参数,主要应对GET请求,但此种方式

Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案 (精髓)

前言 刚开始创建MVC与Web API的混合项目时,碰到好多问题,今天拿出来跟大家一起分享下.有朋友私信我问项目的分层及文件夹结构在我的第一篇博客中没说清楚,那么接下来我就准备从这些文件怎么分文件夹说起.问题大概有以下几点: 1.项目层的文件夹结构 2.解决MVC的Controller和Web API的Controller类名不能相同的问题 3.给MVC不同命名空间的Area的注册不同的路由 4.让Web API路由配置也支持命名空间参数 5.MVC及Web API添加身份验证及错误处理的过滤器

Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案

前言 刚开始创建MVC与Web API的混合项目时,碰到好多问题,今天拿出来跟大家一起分享下.有朋友私信我问项目的分层及文件夹结构在我的第一篇博客中没说清楚,那么接下来我就准备从这些文件怎么分文件夹说起.问题大概有以下几点: 1.项目层的文件夹结构 2.解决MVC的Controller和Web API的Controller类名不能相同的问题 3.给MVC不同命名空间的Area的注册不同的路由 4.让Web API路由配置也支持命名空间参数 5.MVC及Web API添加身份验证及错误处理的过滤器

ASP.NET Web API Model-ParameterBinding

ASP.NET Web API Model-ParameterBinding 前言 通过上个篇幅的学习了解Model绑定的基础知识,然而在ASP.NET Web API中Model绑定功能模块并不是被直接调用的,而是要通过本篇要介绍的内容ParameterBinding的一系列对象对其进行封装调用,通过本篇的学习之后也会大概的清楚在Web API中绑定会有哪几种方式. Model-ParameterBinding(对象篇) 在ASP.NET Web API中ParameterBinding代表着

ASP.NET Web API - ASP.NET MVC 4 系列

       Web API 项目是 Windows 通信接口(Windows Communication Foundation,WCF)团队及其用户激情下的产物,他们想与 HTTP 深度整合.WCF 进行 Web 服务编程的迭代是一个抽象事务,主要为了隐藏像传输细节一样的内容.Web API 试图彻底颠覆这一过程,去掉 WCF 中的大部分层,而允许开发人员直接访问 HTTP 编程模型的所有方面.        ASP.NET MVC 在接收表单数据生成 HTML 方面功能非常强大:ASP.NE