你可以定義你自己的DefaultActionValueBinder。然後你可以從身體和uri混合搭配。這裏是一個博客帖子,裏面有一個Web API的MvcActionValueBinder示例。使您自己的DefaultActionValueBinder成爲首選的解決方案,因爲它確保在執行任何其他ActionFilterAttribute之前,活頁夾將完成。
http://blogs.msdn.com/b/jmstall/archive/2012/04/18/mvc-style-parameter-binding-for-webapi.aspx
UPDATE:
我遇到了一些麻煩,在博客文章的實施,並試圖得到它使用我的自定義介質格式化。幸運的是,我的所有請求對象都是從基類中擴展的,所以我創建了自己的格式化程序。
在WebApiConfig
config.ParameterBindingRules.Insert(0, descriptor => descriptor.ParameterType.IsSubclassOf(typeof (Request)) ? new BodyAndUriParameterBinding(descriptor) : null);
BodyAndUriParameterBinding。CS
public class BodyAndUriParameterBinding : HttpParameterBinding
{
private IEnumerable<MediaTypeFormatter> Formatters { get; set; }
private IBodyModelValidator BodyModelValidator { get; set; }
public BodyAndUriParameterBinding(HttpParameterDescriptor descriptor)
: base (descriptor)
{
var httpConfiguration = descriptor.Configuration;
Formatters = httpConfiguration.Formatters;
BodyModelValidator = httpConfiguration.Services.GetBodyModelValidator();
}
private Task<object> ReadContentAsync(HttpRequestMessage request, Type type,
IEnumerable<MediaTypeFormatter> formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
{
var content = request.Content;
if (content == null)
{
var defaultValue = MediaTypeFormatter.GetDefaultValueForType(type);
return defaultValue == null ? Task.FromResult<object>(null) : Task.FromResult(defaultValue);
}
return content.ReadAsAsync(type, formatters, formatterLogger, cancellationToken);
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext,
CancellationToken cancellationToken)
{
var paramFromBody = Descriptor;
var type = paramFromBody.ParameterType;
var request = actionContext.ControllerContext.Request;
var formatterLogger = new ModelStateFormatterLogger(actionContext.ModelState, paramFromBody.ParameterName);
return ExecuteBindingAsyncCore(metadataProvider, actionContext, paramFromBody, type, request, formatterLogger, cancellationToken);
}
// Perf-sensitive - keeping the async method as small as possible
private async Task ExecuteBindingAsyncCore(ModelMetadataProvider metadataProvider, HttpActionContext actionContext,
HttpParameterDescriptor paramFromBody, Type type, HttpRequestMessage request, IFormatterLogger formatterLogger,
CancellationToken cancellationToken)
{
var model = await ReadContentAsync(request, type, Formatters, formatterLogger, cancellationToken);
if (model != null)
{
var routeParams = actionContext.ControllerContext.RouteData.Values;
foreach (var key in routeParams.Keys.Where(k => k != "controller"))
{
var prop = type.GetProperty(key, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
if (prop == null)
{
continue;
}
var descriptor = TypeDescriptor.GetConverter(prop.PropertyType);
if (descriptor.CanConvertFrom(typeof(string)))
{
prop.SetValue(model, descriptor.ConvertFromString(routeParams[key] as string));
}
}
}
// Set the merged model in the context
SetValue(actionContext, model);
if (BodyModelValidator != null)
{
BodyModelValidator.Validate(model, type, metadataProvider, actionContext, paramFromBody.ParameterName);
}
}
}
如果您從'UpdateProduct'的'Id'和它到你的動作簽名:'公共HttpResponseMessage把(INT ID,UpdateProduct中模型)'這也將工作沒有任何自定義模型粘合劑。 – nemesv
看看這篇文章看起來這是你需要的:http://blogs.msdn.com/b/jmstall/archive/2012/04/18/mvc-style-parameter-binding-for-webapi.aspx – nemesv
Did你有沒有找到解決這個問題的方法?我有同樣的問題。在我看來,這是一個非常愚蠢和不直觀的行爲。 –