asp.net - Modell bei Verwendung von WebAPI erneut validieren (TryValidateModel-Äquivalent)

Translate

Mit Vanilla MVC kann ich mein Modell mit TryValidateModel erneut validieren. Die TryValidateModel-Methode scheint nicht auf WebAPI anwendbar zu sein. Wie kann ich mein Modell bei Verwendung von WebAPI erneut validieren?

This question and all comments follow the "Attribution Required."

Alle Antworten

Translate

Ich weiß, dass es eine Weile her ist, seit dies gefragt wurde, aber das Problem ist immer noch gültig. Daher dachte ich, ich sollte meine Lösung für dieses Problem teilen. Ich habe mich entschlossen, das TryValidateModel (Objektmodell) selbst zu implementieren, basierend auf der Implementierung in System.Web.Mvc.Controller.cs

Das Problem ist, dass das TryValidateModel des MVC intern seinen eigenen HttpContext und ModelState verwendet. Wenn Sie die beiden vergleichen, sind sie sich sehr ähnlich ...

Um unseren eigenen HttpContext verwenden zu können, gibt es einen HttpContextWrapper, der dafür verwendet werden kann.
Und da wir unseren Modellstatus löschen müssen, spielt es keine Rolle, dass wir einen anderen ModelState-Typ verwenden, solange wir das gewünschte Ergebnis erzielen. Daher erstelle ich ein neues ModelState-Objekt aus dem richtigen Typ ...
Ich habe den Fehler zum ModelState des Controllers und nicht zum Modellstatus des neu erstellten ModelState hinzugefügt. Dies scheint für mich in Ordnung zu sein :)
Hier ist mein Code, den ich gerade zum Controller hinzugefügt habe ...
Vergessen Sie nicht, die Bibliothek zu importieren ...

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;
    }
Quelle
hex
Translate

Ich weiß nicht, wann es hinzugefügt wurde, aber jetzt gibt es die Validate-Methode auf dem API-Controller.

ApiController.Validate-Methode (TEntity)https://msdn.microsoft.com/en-us/library/dn573258%28v=vs.118%29.aspx

Quelle
Translate

Basierend aufrik-vanmechelenUrsprüngliche Antwort: Hier ist meine Version, die auf dem von der Web-API bereitgestellten Service-Container basiert.

    /// <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;
    }

Hierbei werden die folgenden einfachen Erweiterungsmethoden verwendet, um auf die Dienste zuzugreifen:

  /// <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>();
    }
}

Der Vorteil dieser Methode besteht darin, dass die MetadataProvider und ValidatorProvider, die Sie für Ihre Web-API-Anwendung konfiguriert haben, wiederverwendet werden, während die vorherige Antwort die in ASP.NET MVC konfigurierte Antwort abruft. ASP.NET MVC und WebAPI werden über verschiedene Pipelines ausgeführt.

Quelle
Translate

Es stellt sich heraus, dass TryValidateModel in WebAPI nicht unterstützt wird. Es gibt eine Funktionsanforderung für CodePlex.

Quelle
Leave a Reply
You must be logged in to post a answer.
Über den Autor