WebApi:ApiExplorer 和自定义 ModelBinders
WebApi: ApiExplorer and Custom ModelBinders
我的大部分 api 路线都是这样分段的:
/api/{segment}/MyEntity
(即“/api/SegmentA/MyEntity”)
我定义了一个 ModelBinder,它将字符串转换为 Segment
对象,如下所示:
class SegmentModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null || String.IsNullOrEmpty(value.AttemptedValue))
return false;
bindingContext.Model = **logic to find segment object from value.AttemptedValue**;
return true;
}
}
配置为:
GlobalConfiguration.Configuration.BindParameter(typeof(Segment), new SegmentModelBinder());
所以我的路线最终看起来像这样:
public class MyEntityController : BaseController
{
[HttpGet, Route("api/{segment}/MyEntity")]
public IEnumerable<MyEntity> Get(Segment segment)
{
...
}
}
问题是,我现在正在尝试为这些 Api 调用生成文档,而 ApiExplorer
完全被这些路由搞糊涂了,并忽略了它们。
我如何告诉它对于这些路由,当它看到 Segment
类型的参数时,它真的只是来自路由的字符串?
从使用 ModelBinder
切换到 TypeConverter
解决了问题:
[TypeConverter(typeof(MyEntityConverter))]
public class MyEntity
{....
-
public class MyEntityConverter : 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, System.Globalization.CultureInfo culture, object value)
{
var key = value as string;
if (!String.IsNullOrEmpty(key))
return **Find Entity**;
return base.ConvertFrom(context, culture, value);
}
}
编辑:
如果你曾经 return 这个实体在调用中,你也需要它,否则 newtonsoft json 序列化程序会将 class 序列化为类型名称:
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return false;
}
我的大部分 api 路线都是这样分段的:
/api/{segment}/MyEntity
(即“/api/SegmentA/MyEntity”)
我定义了一个 ModelBinder,它将字符串转换为 Segment
对象,如下所示:
class SegmentModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null || String.IsNullOrEmpty(value.AttemptedValue))
return false;
bindingContext.Model = **logic to find segment object from value.AttemptedValue**;
return true;
}
}
配置为:
GlobalConfiguration.Configuration.BindParameter(typeof(Segment), new SegmentModelBinder());
所以我的路线最终看起来像这样:
public class MyEntityController : BaseController
{
[HttpGet, Route("api/{segment}/MyEntity")]
public IEnumerable<MyEntity> Get(Segment segment)
{
...
}
}
问题是,我现在正在尝试为这些 Api 调用生成文档,而 ApiExplorer
完全被这些路由搞糊涂了,并忽略了它们。
我如何告诉它对于这些路由,当它看到 Segment
类型的参数时,它真的只是来自路由的字符串?
从使用 ModelBinder
切换到 TypeConverter
解决了问题:
[TypeConverter(typeof(MyEntityConverter))]
public class MyEntity
{....
-
public class MyEntityConverter : 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, System.Globalization.CultureInfo culture, object value)
{
var key = value as string;
if (!String.IsNullOrEmpty(key))
return **Find Entity**;
return base.ConvertFrom(context, culture, value);
}
}
编辑:
如果你曾经 return 这个实体在调用中,你也需要它,否则 newtonsoft json 序列化程序会将 class 序列化为类型名称:
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return false;
}