ASP.NET MVC Bei Verwendung eines benutzerdefinierten Modellbinders wurde vom Client ein potenziell gefährlicher Request.Form-Wert erkannt

95

Hier wird der Fehler angezeigt:

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

Wie erlaube ich nur eine Auswahl von Werten? dh

[ValidateInput(false)]
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    ValueProviderResult value = bindingContext.ValueProvider.GetValue("ConfirmationMessage");
    ValueProviderResult value2 = bindingContext.ValueProvider.GetValue("ConfirmationMessage2");
}
DW
quelle
1
Mögliches Duplikat von Ein potenziell gefährlicher Request.Form-Wert wurde vom Client erkannt , unabhängig davon, ob es sich um Webforms oder MVC handelt.
Erik Philips
2
Danke, aber Sie haben mein Problem nicht als anders angesehen
DW
Das gleiche Problem besteht darin, dass es möglicherweise MVC-spezifische Möglichkeiten gibt, damit umzugehen.
Erik Philips
Wenn Sie EF verwenden, lesen Sie die Antwort von bizzehdee
Petr

Antworten:

222

Sie haben einige Möglichkeiten.

Fügen Sie im Modell dieses Attribut zu jeder Eigenschaft hinzu, die Sie benötigen, um HTML zuzulassen - beste Wahl

using System.Web.Mvc;

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

Fügen Sie in der Controller-Aktion dieses Attribut hinzu, um den gesamten HTML-Code zuzulassen

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

Brute Force in web.config - definitiv nicht empfohlen

Fügen Sie in der Datei web.config innerhalb der Tags das Element httpRuntime mit dem Attribut requestValidationMode = "2.0" ein. Fügen Sie außerdem das Attribut validateRequest = "false" in das Element pages ein.

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

Weitere Informationen: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

Das Obige funktioniert für die Verwendung des Standard-Modellbinders.

Benutzerdefinierter ModelBinder

Es scheint, dass ein Aufruf von bindingContext.ValueProvider.GetValue () im obigen Code die Daten unabhängig von den Attributen immer überprüft. Das Durchsuchen der ASP.NET MVC-Quellen zeigt, dass der DefaultModelBinder zuerst prüft, ob eine Anforderungsvalidierung erforderlich ist, und dann die Methode bindingContext.UnvalidatedValueProvider.GetValue () mit einem Parameter aufruft, der angibt, ob eine Validierung erforderlich ist oder nicht.

Leider können wir keinen Framework-Code verwenden, da er versiegelt, privat oder was auch immer ist, um ignorante Entwickler vor gefährlichen Dingen zu schützen. Es ist jedoch nicht allzu schwierig, einen funktionierenden benutzerdefinierten Modellordner zu erstellen, der die Attribute AllowHtml und ValidateInput berücksichtigt:

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...
        }
    }
}

Das andere erforderliche Stück ist eine Möglichkeit, einen nicht validierten Wert abzurufen. In diesem Beispiel verwenden wir eine Erweiterungsmethode für die ModelBindingContext-Klasse:

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

Weitere Informationen hierzu finden Sie unter http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/

ericdc
quelle
Ich habe dies auf dem Controller [HttpPost, ValidateInput (false)] und ich erhalte immer noch den Fehler
DW
Sehen Sie meine überarbeitete Antwort mit einem Weg, um dies zu umgehen, wenn Sie einen benutzerdefinierten Modellbinder verwenden
ericdc
Danke, aber es gefällt dieser Zeile nicht. BindingContext.GetValueFromValueProvider
DW
GetValueFromValueProvider muss sich in einer öffentlichen statischen Klasse befinden. Überprüfen Sie die Änderungen oben.
Ericdc
Ta, valueProviderResult reutrns null tho? var valueProviderResult = bindingContext.GetValueFromValueProvider (shouldPerformRequestValidation);
DW
30

Versuchen:

HttpRequestBase request = controllerContext.HttpContext.Request;
string re = request.Unvalidated.Form.Get("ConfirmationMessage")
DW
quelle
Wenn ich dies versuche, erhalte ich eine Ausnahme, die besagt: Das nicht aufrufbare Mitglied 'System.web.HttpRequestBase.Unvalidated' kann nicht wie eine Methode verwendet werden. Hat sich das geändert?
Stack0verflow
7
Die zweite Zeile sollte wirklich seinvar re = request.Unvalidated.Form["ConfirmationMessage"];
Stack0verflow
4

Um die Antwort von @DW in meinem Edit-Controller zu erweitern und über Formularwerte zu iterieren, musste ich alle Instanzen von Request.Params.AllKeyswith Request.Unvalidated.Form.AllKeysund alle Instanzen von Request[key]with ersetzen Request.Unvalidated.Form[key].

Dies war die einzige Lösung, die für mich funktioniert hat.

Mike Godin
quelle
0

Wie Mike Godin schrieb, müssen Sie, selbst wenn Sie das Attribut [ValidateInput (false)] festlegen, Request.Unvalidated.Form anstelle von Request.Form verwenden. Dies funktionierte bei mir mit ASP.NET MVC 5

Ryozzo
quelle
1
Dies war tatsächlich ein nützlicher Rat, da der Zugriff auf Daten von einem Basis-Controller (dh für Protokoll- oder Debug-Zwecke) bei jedem Zugriff auf Request.Form eine Ausnahme auslöst, selbst wenn das Modell über dieses Attribut verfügt.
nsimeonov
-5

Hier sind die Schritte zum Codieren auf Clientebene und zum Decodieren auf Serverebene:

  1. Veröffentlichen Sie das Formular mit der jquery submit-Methode.

  2. Klicken Sie in der jquery-Schaltfläche auf das Codierungsfeld für die Ereignismethode, das Sie auf dem Server veröffentlichen möchten. Beispiel:

    $("#field").val(encodeURIComponent($("#field").val()))
    $("#formid").submit();
  3. Greifen Sie in Controller Level auf alle Formular-ID-Werte mit zu

    HttpUtility.UrlDecode(Request["fieldid"])

Beispielbeispiel:

  • Controller-Ebene:

    public ActionResult Name(string id)
    {
    
        CheckDispose();
        string start = Request["start-date"];
        string end = Request["end-date"];
        return View("Index", GetACPViewModel(HttpUtility.UrlDecode(Request["searchid"]), start, end));
    }
  • Kundenebene:

    <% using (Html.BeginForm("Name", "App", FormMethod.Post, new { id = "search-form" }))
    { %>
    <div>
    <label  for="search-text" style="vertical-align: middle" id="search-label" title="Search for an application by name, the name for who a request was made, or a BEMSID">App, (For Who) Name, or BEMSID: </label>
    <%= Html.TextBox("searchid", null, new {value=searchText, id = "search-text", placeholder = "Enter Application, Name, or BEMSID" })%>
    </div>
    <div>
    <input id="start-date" name="start-date" class="datepicker" type="text"  placeholder="Ex: 1/1/2012"/>
    </div>
    <div>
    <input id="end-date" name="end-date" class="datepicker" type="text"  placeholder="Ex: 12/31/2012"/>
    </div>
    <div>
    <input type="button" name="search" id="btnsearch" value="Search" class="searchbtn" style="height:35px"/>
    </div> 
    <% } %>

In der Dokumentbereitschaftsfunktion:

$(function () {     
  $("#btnsearch").click(function () {  
    $("#search-text").val(encodeURIComponent($("#search-text").val()));
    $("#search-form").submit();
  });
});
Prakash Rajendran
quelle
4
JQuery- und clientseitige Technologie hat nichts mit MVC zu tun, die Validierung erfolgt serverseitig mit dem MVC-Framework. Es ist keine gültige Antwort
diegosasw
1
Angesichts der Tatsache, dass Microsoft das AllowHtml-Attribut buchstäblich ignoriert und die einzige funktionsfähige Lösung auf der Serverseite darin besteht, die Funktionalität des Standardmodellbinders zu ersetzen, würde ich argumentieren, dass die clientseitige Codierung eine absolut gültige Option ist.
Jonathan