当没有数据发布到 Web 时避免空模型 API
Avoid null model when no data is posted in Web API
这题和我想实现的类似:
Avoiding null model in ASP.Net Web API when no posted properties match the model
但无人回复。
我有一条路线采用 GET 模型:
[HttpGet, Route("accounts")]
public AccountListResult Post(AccountListRequest loginRequest)
{
return accountService.GetAccounts(loginRequest);
}
该模型填充了来自操作过滤器的附加数据。
在这种情况下,所有需要知道的是 UserId,操作过滤器根据 cookie/header 添加到模型中,随请求一起传入。
我想在 WebAPI 中使用所有默认模型绑定,但我想避免空对象。
我认为模型绑定不能解决我的问题。
How do I replace the behaviour of Web API model binding so that instead of Null I receive a new instance when no parameters are passed in
这更接近我想要做的,除了它的每种类型都很乏味。
编辑:由于问题是针对 Web API,我也在下面发布了 Web API 解决方案。
您可以在操作筛选器中执行以下操作。以下代码仅在您的模型包含默认构造函数时才有效。
Web API 实现:
public override void OnActionExecuting(HttpActionContext actionContext)
{
var parameters = actionContext.ActionDescriptor.GetParameters();
foreach (var parameter in parameters)
{
object value = null;
if (actionContext.ActionArguments.ContainsKey(parameter.ParameterName))
value = actionContext.ActionArguments[parameter.ParameterName];
if (value != null)
continue;
value = CreateInstance(parameter.ParameterType);
actionContext.ActionArguments[parameter.ParameterName] = value;
}
base.OnActionExecuting(actionContext);
}
protected virtual object CreateInstance(Type type)
{
// Check for existence of default constructor using reflection if needed
// and if performance is not a constraint.
// The below line will fail if the model does not contain a default constructor.
return Activator.CreateInstance(type);
}
MVC 实现:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var parameters = filterContext.ActionDescriptor.GetParameters();
foreach (var parameter in parameters)
{
if (filterContext.ActionParameters.ContainsKey(parameter.ParameterName))
{
object value = filterContext.ActionParameters[parameter.ParameterName];
if (value == null)
{
// The below line will fail if the model does not contain a default constructor.
value = Activator.CreateInstance(parameter.ParameterType);
filterContext.ActionParameters[parameter.ParameterName] = value;
}
}
}
base.OnActionExecuting(filterContext);
}
@Sarathy 的解决方案有效,但不会触发对其创建的对象的模型验证。这可能会导致将空模型传递给操作但 ModelState.IsValid
仍然计算为真的情况。
为了我自己的目的,有必要在创建空模型对象时触发模型的重新验证:
public override void OnActionExecuting(HttpActionContext actionContext)
{
var parameters = actionContext.ActionDescriptor.GetParameters();
foreach (var parameter in parameters)
{
object value = null;
if (actionContext.ActionArguments.ContainsKey(parameter.ParameterName))
value = actionContext.ActionArguments[parameter.ParameterName];
if (value != null)
continue;
value = Activator.CreateInstance(parameter.ParameterType);
actionContext.ActionArguments[parameter.ParameterName] = value;
var bodyModelValidator = actionContext.ControllerContext.Configuration.Services.GetBodyModelValidator();
var metadataProvider = actionContext.ControllerContext.Configuration.Services.GetModelMetadataProvider();
bodyModelValidator.Validate(value, value.GetType(), metadataProvider, actionContext, string.Empty);
}
base.OnActionExecuting(actionContext);
}
这题和我想实现的类似:
Avoiding null model in ASP.Net Web API when no posted properties match the model
但无人回复。
我有一条路线采用 GET 模型:
[HttpGet, Route("accounts")]
public AccountListResult Post(AccountListRequest loginRequest)
{
return accountService.GetAccounts(loginRequest);
}
该模型填充了来自操作过滤器的附加数据。
在这种情况下,所有需要知道的是 UserId,操作过滤器根据 cookie/header 添加到模型中,随请求一起传入。
我想在 WebAPI 中使用所有默认模型绑定,但我想避免空对象。
我认为模型绑定不能解决我的问题。
How do I replace the behaviour of Web API model binding so that instead of Null I receive a new instance when no parameters are passed in
这更接近我想要做的,除了它的每种类型都很乏味。
编辑:由于问题是针对 Web API,我也在下面发布了 Web API 解决方案。
您可以在操作筛选器中执行以下操作。以下代码仅在您的模型包含默认构造函数时才有效。
Web API 实现:
public override void OnActionExecuting(HttpActionContext actionContext)
{
var parameters = actionContext.ActionDescriptor.GetParameters();
foreach (var parameter in parameters)
{
object value = null;
if (actionContext.ActionArguments.ContainsKey(parameter.ParameterName))
value = actionContext.ActionArguments[parameter.ParameterName];
if (value != null)
continue;
value = CreateInstance(parameter.ParameterType);
actionContext.ActionArguments[parameter.ParameterName] = value;
}
base.OnActionExecuting(actionContext);
}
protected virtual object CreateInstance(Type type)
{
// Check for existence of default constructor using reflection if needed
// and if performance is not a constraint.
// The below line will fail if the model does not contain a default constructor.
return Activator.CreateInstance(type);
}
MVC 实现:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var parameters = filterContext.ActionDescriptor.GetParameters();
foreach (var parameter in parameters)
{
if (filterContext.ActionParameters.ContainsKey(parameter.ParameterName))
{
object value = filterContext.ActionParameters[parameter.ParameterName];
if (value == null)
{
// The below line will fail if the model does not contain a default constructor.
value = Activator.CreateInstance(parameter.ParameterType);
filterContext.ActionParameters[parameter.ParameterName] = value;
}
}
}
base.OnActionExecuting(filterContext);
}
@Sarathy 的解决方案有效,但不会触发对其创建的对象的模型验证。这可能会导致将空模型传递给操作但 ModelState.IsValid
仍然计算为真的情况。
为了我自己的目的,有必要在创建空模型对象时触发模型的重新验证:
public override void OnActionExecuting(HttpActionContext actionContext)
{
var parameters = actionContext.ActionDescriptor.GetParameters();
foreach (var parameter in parameters)
{
object value = null;
if (actionContext.ActionArguments.ContainsKey(parameter.ParameterName))
value = actionContext.ActionArguments[parameter.ParameterName];
if (value != null)
continue;
value = Activator.CreateInstance(parameter.ParameterType);
actionContext.ActionArguments[parameter.ParameterName] = value;
var bodyModelValidator = actionContext.ControllerContext.Configuration.Services.GetBodyModelValidator();
var metadataProvider = actionContext.ControllerContext.Configuration.Services.GetModelMetadataProvider();
bodyModelValidator.Validate(value, value.GetType(), metadataProvider, actionContext, string.Empty);
}
base.OnActionExecuting(actionContext);
}