使用Web API时验证模型(TryValidateModel等效项)

时间:2012-10-16 01:32:02

标签: asp.net asp.net-mvc asp.net-web-api

使用vanilla MVC我可以使用TryValidateModel重新验证我的模型。 TryValidateModel方法似乎不适用于WebAPI。如何在使用WebAPI时重新验证我的模型?

4 个答案:

答案 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上有一项功能请求。