使用vanilla MVC我可以使用TryValidateModel重新验证我的模型。 TryValidateModel方法似乎不适用于WebAPI。如何在使用WebAPI时重新验证我的模型?
答案 0 :(得分:10)
我知道已经有一段时间了,但是这个问题仍然有效。因此,我认为我应该分享我对这个问题的解决方案。 我决定自己实现TryValidateModel(对象模型),基于System.Web.Mvc.Controller.cs中的实现
问题是mvc的TryValidateModel内部使用了自己的HttpContext和ModelState。如果你去和两者相媲美,它们非常相似......
能够使用我们自己的HttpContext存在一个可以用于它的HttpContextWrapper。
由于我们必须清除模型状态,因此我们使用不同类型的ModelState并不重要,只要我们得到所需的结果,因此我从正确的类型创建一个新的ModelState对象...
我确实将错误添加到控制器的ModelState,而不是模型状态添加到新创建的ModelState,这似乎对我来说很好:)
这是我的代码,我刚刚添加到控制器...
别忘了导入图书馆......
using System.Web.ModelBinding;
protected internal bool TryValidateModel(object model)
{
return TryValidateModel(model, null /* prefix */);
}
protected internal bool TryValidateModel(object model, string prefix)
{
if (model == null)
{
throw new ArgumentNullException("model");
}
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
var t = new ModelBindingExecutionContext(new HttpContextWrapper(HttpContext.Current), new System.Web.ModelBinding.ModelStateDictionary());
foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(metadata, t).Validate(null))
{
ModelState.AddModelError(validationResult.MemberName, validationResult.Message);
}
return ModelState.IsValid;
}
答案 1 :(得分:5)
我不知道它何时被添加但现在api控制器上有Validate方法。
ApiController.Validate方法(TEntity) https://msdn.microsoft.com/en-us/library/dn573258%28v=vs.118%29.aspx
答案 2 :(得分:3)
基于rik-vanmechelen原始答案,这是我的版本,它依赖于Web API公开的服务容器。
/// <summary>
/// Tries to validate the model.
/// </summary>
/// <param name="model">The model.</param>
/// <returns>Whether the model is valid or not.</returns>
protected internal bool TryValidateModel(object model)
{
if (model == null)
{
throw new ArgumentNullException("model");
}
var metadataProvider = Configuration.Services.GetService<System.Web.Http.Metadata.ModelMetadataProvider>();
var validatorProviders = Configuration.Services.GetServices<System.Web.Http.Validation.ModelValidatorProvider>();
var metadata = metadataProvider.GetMetadataForType(() => model, model.GetType());
ModelState.Clear();
var modelValidators = metadata.GetValidators(validatorProviders);
foreach (var validationResult in modelValidators.SelectMany(v => v.Validate(metadata, null)))
{
ModelState.AddModelError(validationResult.MemberName, validationResult.Message);
}
return ModelState.IsValid;
}
这使用以下简单的扩展方法来访问服务:
/// <summary>
/// Services container extension methods.
/// </summary>
public static class ServicesContainerExtensions
{
/// <summary>
/// Gets the service.
/// </summary>
/// <typeparam name="TService">The type of the service.</typeparam>
/// <param name="services">The services.</param>
/// <returns>The service.</returns>
/// <exception cref="System.ArgumentNullException">services</exception>
public static TService GetService<TService>(this ServicesContainer services)
{
if (services == null)
{
throw new ArgumentNullException("services");
}
return (TService)((object)services.GetService(typeof(TService)));
}
/// <summary>
/// Gets the services.
/// </summary>
/// <typeparam name="TService">The type of the service.</typeparam>
/// <param name="services">The services.</param>
/// <returns>The services.</returns>
/// <exception cref="System.ArgumentNullException">services</exception>
public static IEnumerable<TService> GetServices<TService>(this ServicesContainer services)
{
if (services == null)
{
throw new ArgumentNullException("services");
}
return services.GetServices(typeof(TService)).Cast<TService>();
}
}
使用此方法的优点是它重用了为Web API应用程序配置的MetadataProvider和ValidatorProvider,而前一个答案是检索ASP.NET MVC中配置的那个。 ASP.NET MVC和WebAPI贯穿不同的管道。
答案 3 :(得分:1)
结果是WebAPI不支持TryValidateModel。 CodePlex上有一项功能请求。