当前位置:首页 > Windows程序 > 正文

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

2021-03-18 Windows程序

原文地址:Parameter Binding in ASP.NET Web API

译文如下:

当Web API相应Controller的一个方法时,它必定存在一个设置参数的过程,叫作数据绑定。这篇文章描述了Web API如何绑定参数以及如何自定义绑定过程。

一般情况下,Web API绑定参数符合如下规则:

  典型Web API Controller方法的例子:

HttpResponseMessage Put(int id, Product item) { ... }

  参数id是简单类型,所以webapi试图从URI中获取值。参数item为复杂类型,所以web api 使用 media-type 类型从request body中读取。

  从URI中获取值,Web API会从路由或者URI的查询参数中获取。路由数据例子如下:"api/{controller}/public/{category}/{id}",更多细节可参考:Routing and Action Selection.

  在余下的文章中,我将给你介绍的是如何自定义参数绑定的过程。对于复杂类型,当然最好尽可能考虑media-type类型转化。一个http的关键原理是:资源是保存在message body 中被传递的,使用内容协商来指定资源如何表示。media-type 类型就是被设计来实现这个目标的。

使用[FromUri]

  在参数前添加[FromUri]属性可以强制Web API 从URI中读取复杂类型。下面的例子定义了GeoPoint类型,以及一个从URI中获取GeoPoint的controller方法。

public class GeoPoint { public double Latitude { get; set; } public double Longitude { get; set; } } public ValuesController : ApiController { public HttpResponseMessage Get([FromUri] GeoPoint location) { ... } }

  客户端可以通过查询字符将两个参数传递给Web API。例子如下:

?Latitude=47.678558&Longitude=-122.130989

使用【FromBody】

  给参数添加[FromBody]属性可以迫使Web API从request body 中读取简单参数。

public HttpResponseMessage Post([FromBody] string name) { ... }

  在这个例子中WebAPI将使用一个 media-type 转化器从Request body 中读取name的值。

POST :5076/api/values HTTP/1.1 User-Agent: Fiddler Host: localhost:5076 Content-Type: application/json Content-Length: 7 "Alice"

  当一个参数标记[FromBody]后Web API通过Content-Type header选择格式。在这个例子中,content type 是“application/json” 并且request body是原始的Json字符串(不是Json对象)。

  有而且只有一个参数允许从message body 中读取,下面的例子将不会成功:

// Caution: Will not work! public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

  这条规则的原因为:request body 可能存储在一个只能读取一次的非缓冲的数据流中。

Type Converters

  创建一个TypeConverter并提供一个字符串转化,你就可以使Web API像对待一个简单类型那样对待一个类(所以Web API会尝试从URI中获取绑定的数据)。

   下面的代码展示了一个GeoPoint类代表地理坐标,,添加TypeConvert方法将字符串转化为GeoPoint实例。GeoPoint类添加了[TypeConvert]属性,制定类型转化器。(这个例子取自Mike Stall的博客文章How to bind to custom objects in action signatures in MVC/WebAPI)

[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); } }

  现在Web API将GeoPoint视为简单类型,也就是说他会试图从URL中获取GeoPoint参数,而不用在参数前添加[FromUri]

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

  客户端请求的URI就像这样:

?location=47.678558,-122.130989

Model Binders

  操控类型转化更强的是创建自定义对象绑定Model Binder。使用Model Binder,你可以接收一个Http请求,一个Action和一个路由数据的原始值。

  创建一个Model Binder,需要继承IModelBinder接口,这个接口只定义了一个方法BindModel

bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext);

  下面是GeoPoint对象的Model Binder

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/63193.html