web-dev-qa-db-fra.com

ASP.NET MVC Une valeur Request.Form potentiellement dangereuse a été détectée par le client lors de l'utilisation d'un modelbinder personnalisé.

Obtenir l'erreur ici:

ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");

Comment autoriser une sélection de valeurs uniquement? c'est à dire.

[ValidateInput(false)]
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");
    ValueProviderResult value2 = bindingContext.ValueProvider.GetValue("ConfirmationMessage2");
}
90
D-W

Vous avez quelques options.

Sur le modèle, ajoutez cet attribut à chaque propriété dont vous avez besoin pour autoriser HTML - meilleur choix

using System.Web.Mvc;

[AllowHtml]
public string SomeProperty { get; set; }

Sur l’action du contrôleur, ajoutez cet attribut pour autoriser tout le code HTML.

[ValidateInput(false)]
public ActionResult SomeAction(MyViewModel myViewModel)

La force brute dans web.config - n'est absolument pas recommandée

Dans le fichier web.config, insérez l'élément httpRuntime avec l'attribut requestValidationMode = "2.0" dans les balises. Ajoutez également l'attribut validateRequest = "false" dans l'élément pages.

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>

Plus d'infos: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

Ce qui précède fonctionne pour les utilisations du modelbinder par défaut.

ModelBinder personnalisé

Il semble qu'un appel à bindingContext.ValueProvider.GetValue () dans le code ci-dessus valide toujours les données, quels que soient les attributs. En fouillant dans les sources ASP.NET MVC, il apparaît que DefaultModelBinder vérifie d’abord si la validation de la demande est requise, puis appelle la méthode bindingContext.UnvalidatedValueProvider.GetValue () avec un paramètre indiquant si la validation est requise ou non.

Malheureusement, nous ne pouvons utiliser aucun des codes de l’infrastructure car ils sont scellés, privés ou autres pour empêcher les développeurs ignorants de faire des choses dangereuses, mais il n’est pas trop difficile de créer un classeur de modèle personnalisé qui respecte les attributs AllowHtml et ValidateInput:

public class MyModelBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // First check if request validation is required
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && bindingContext.ModelMetadata.RequestValidationEnabled;

        // Get value
        var valueProviderResult = bindingContext.GetValueFromValueProvider(shouldPerformRequestValidation);
        if (valueProviderResult != null)
        {
            var theValue = valueProviderResult.AttemptedValue;

            // etc...
        }
    }
}

L'autre élément requis est un moyen de récupérer une valeur non validée. Dans cet exemple, nous utilisons une méthode d'extension pour la classe ModelBindingContext:

public static class ExtensionHelpers
{
    public static ValueProviderResult GetValueFromValueProvider(this ModelBindingContext bindingContext, bool performRequestValidation)
    {
        var unvalidatedValueProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;
        return (unvalidatedValueProvider != null)
          ? unvalidatedValueProvider.GetValue(bindingContext.ModelName, !performRequestValidation)
          : bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
    }
}

Plus d'informations à ce sujet sur http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/

209
ericdc

Essayer:

HttpRequestBase request = controllerContext.HttpContext.Request;
string re = request.Unvalidated.Form.Get("ConfirmationMessage")
29
D-W

En développant la réponse de @ D-W, dans mon contrôleur de montage, en itérant sur les valeurs de formulaire, je devais remplacer toutes les instances de Request.Params.AllKeys avec Request.Unvalidated.Form.AllKeys et toutes les instances de Request[key] avec Request.Unvalidated.Form[key].

C'était la seule solution qui a fonctionné pour moi.

2
Mike Godin