翻译自: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。
对于这个api:
Public HttpResponseMessage Put(int id, Employee employee)
{
…
…
}
web api 从url中获取id类型,从body中获取employee类型。
当然这是默认情况,我们可以强制web api通过fromurl和frombody特性从url或者从body获取。
fromuri 特性
public class TestData
{
public string Name
{
get;
set;
}
public int Id
{
get;
set;
}
}
public HttpResponseMessage Get([FromUri] TestData data)
{……
return Request.CreateResponse(HttpStatusCode.OK, true);
}
这样就可以强制从url获取参数,web api生成TestData类。url:http://localhost:24367/api/Employee?Name=Jignesh&Id=10
可以测试下,这样没任何问题。
fromBody 特性
[HttpPost]
public HttpResponseMessage Post([FromBody] string name)
{
……
return Request.CreateResponse(HttpStatusCode.OK, true);
}
对于这个api,调用时要设置content type:“application/json”
这样设置可以成功调用。
这样就不成功了,web api 支持json string,不支持json 对象,因此只允许在body中有一个参数。
Type converters
可以使用类型转换的方法,将请求的数据按字符串处理,处理过程如下:
namespace WebAPITest
{
using System;
using System.ComponentModel;
using System.Globalization;
public class TestTypeConverter: TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
returntrue;
}
returnbase.CanConvertFrom(context, sourceType);
} public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string)
{
TestData data;
if (TestData.TryParse((string) value, out data))
{
return data;
}
}
return base.ConvertFrom(context, culture, value);
}
}
}
namespaceWebAPITest
{
using System.ComponentModel;
[TypeConverter(typeof(TestTypeConverter))]
public class TestData
{
public string Name
{
get;
set;
}
public int Id
{
get;
set;
} public static bool TryParse(string s, outTestData result)
{
result = null; var parts = s.Split(',');
if (parts.Length != )
{
return false;
} int id;
string name = parts[];
if (int.TryParse(parts[], out id))
{
result = newTestData()
{
Id = id, Name = name
};
return true;
}
return false;
}
}
}
这样就可以不用写from url这样调用: http://localhost:24367/api/Employee?data=10,jignesh%20trivedi
public HttpResponseMessage Get(TestData data)
{
……
return Request.CreateResponse(HttpStatusCode.OK, true);
}
Model Binder
另外一种处理参数的方法,实现IModelBinder 接口,只用实现一个方法BindModel,下面的代码从路由中读取raw data,将其转换成TestData,实例是一个简单类型转换,当然Model binder不限于简单类型:
namespace WebAPITest
{
using System;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;
public class CustomModelBinder: IModelBinder
{
static CustomModelBinder()
{ } public bool BindModel(HttpActionContextactionContext, ModelBindingContextbindingContext)
{
if (bindingContext.ModelType != typeof(TestData))
{
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");
returnfalse;
}
TestData result = newTestData(); var data = key.Split(newchar[]
{
','
});
if (data.Length > )
{
result.Id = Convert.ToInt32(data[]);
result.Name = data[];
bindingContext.Model = result;
return true;
} bindingContext.ModelState.AddModelError(
bindingContext.ModelName, "Cannot convert value to TestData");
return false;
}
}
}
另外需要注册这个binder,我们需要在configuration中生成一个 model-binder provider 。这里使用自带的provider:SimpleModelBinderProvider
namespace WebAPITest
{
using System.Web.Http;
using System.Web.Http.ModelBinding;
using System.Web.Http.ModelBinding.Binders;
public static class WebApiConfig
{
public static void Register(HttpConfigurationconfig)
{
var provider = newSimpleModelBinderProvider(
typeof(TestData), newCustomModelBinder());
config.Services.Insert(typeof(ModelBinderProvider), , provider); config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new
{
id = RouteParameter.Optional
});
}
}
}
调用这个url:URI: http://localhost:24367/api/Employee?data=10,jignesh%20trivedi,有多种方法使用这个Model binder。在参数上使用特性:
public HttpResponseMessage Get([ModelBinder(typeof(CustomModelBinder))] TestData data) {
……
return Request.CreateResponse(HttpStatusCode.OK, true);
}
另外可以在类上使用这个特性:
[ModelBinder(typeof(CustomModelBinder))]
public class TestData
{
//......
}
完了。。。。。