ASP.NET MVC Un valore Request.Form potenzialmente pericoloso è stato rilevato dal client quando si utilizza un modelbinder personalizzato


95

Ottenere l'errore qui:

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

Come posso consentire solo una selezione di valori? cioè

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

1
Possibile duplicato di Un valore Request.Form potenzialmente pericoloso è stato rilevato dal client , non importa se si tratta di Webforms o MVC.
Erik Philips

2
Grazie, ma non hai considerato il mio problema come se fosse diverso
DW

Lo stesso problema alla radice esatto, l'unica differenza è che potrebbero esserci modi specifici MVC per affrontarlo.
Erik Philips

Quando si utilizza EF, vedi risposta bizzehdee qui stackoverflow.com/questions/17964313/...~~V~~singular~~3rd
Petr

Risposte:


223

Hai alcune opzioni.

Sul modello aggiungi questo attributo a ciascuna proprietà di cui hai bisogno per consentire HTML: la scelta migliore

using System.Web.Mvc;

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

Nell'azione del controller aggiungere questo attributo per consentire tutto l'HTML

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

Forza bruta in web.config - decisamente sconsigliato

Nel file web.config, all'interno dei tag, inserire l'elemento httpRuntime con l'attributo requestValidationMode = "2.0". Aggiungi anche l'attributo validateRequest = "false" nell'elemento pages.

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

Maggiori informazioni: http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

Quanto sopra funziona per gli usi del modelbinder predefinito.

ModelBinder personalizzato

Sembra che una chiamata a bindingContext.ValueProvider.GetValue () nel codice precedente convalidi sempre i dati, indipendentemente dagli attributi. L'analisi delle origini ASP.NET MVC rivela che DefaultModelBinder verifica prima se è richiesta la convalida della richiesta e quindi chiama il metodo bindingContext.UnvalidatedValueProvider.GetValue () con un parametro che indica se la convalida è richiesta o meno.

Sfortunatamente non possiamo utilizzare nessuno dei codici del framework perché è sigillato, privato o qualsiasi altra cosa per proteggere gli sviluppatori ignoranti dal fare cose pericolose, ma non è troppo difficile creare un raccoglitore di modelli personalizzato funzionante che rispetti gli attributi AllowHtml e 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'altro pezzo richiesto è un modo per recuperare un valore non convalidato. In questo esempio utilizziamo un metodo di estensione per 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);
    }
}

Maggiori informazioni su questo su http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/


ho questo sul controller [HttpPost, ValidateInput (false)] e ricevo ancora l'errore
DW

Vedere la mia risposta rivista con un modo per aggirare questo problema quando si utilizza un raccoglitore di modelli personalizzato
ericdc,

Grazie, ma non gli piace questa riga bindingContext.GetValueFromValueProvider
DW

GetValueFromValueProvider deve essere in una classe statica pubblica. Controlla le modifiche sopra.
ericdc

Ta, valueProviderResult restituisce null tho? var valueProviderResult = bindingContext.GetValueFromValueProvider (shouldPerformRequestValidation);
DW

31

Provare:

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

Quando lo provo, ottengo un'eccezione che dice: Il membro non invocabile "System.web.HttpRequestBase.Unvalidated" non può essere utilizzato come metodo. Questa cosa è cambiata?
Stack0verflow

7
La seconda riga dovrebbe essere davverovar re = request.Unvalidated.Form["ConfirmationMessage"];
Stack0verflow

5

Espandendo la risposta da @DW, nel mio controller di modifica, nell'iterazione sui valori del modulo, ho dovuto sostituire tutte le istanze di Request.Params.AllKeyscon Request.Unvalidated.Form.AllKeyse tutte le istanze di Request[key]con Request.Unvalidated.Form[key].

Questa era l'unica soluzione che ha funzionato per me.


0

Come ha scritto Mike Godin, anche se imposti l'attributo [ValidateInput (false)], devi usare Request.Unvalidated.Form invece di Request.Form Questo ha funzionato per me con ASP.NET MVC 5


1
Questo è stato effettivamente un consiglio utile, poiché l'accesso ai dati da un controller di base (cioè per scopi di log o debug) qualsiasi accesso a Request.Form genera un'eccezione anche se il modello ha questo attributo.
nsimeonov

-5

Ecco i passaggi per codificare a livello di client e decodificarlo a livello di server:

  1. Pubblica il modulo utilizzando il metodo di invio jquery.

  2. Nel pulsante jquery, fai clic sul campo di codifica del metodo dell'evento che desideri pubblicare sul server. Esempio:

    $("#field").val(encodeURIComponent($("#field").val()))
    $("#formid").submit();
  3. In Controller Level accedi a tutti i form id value utilizzando

    HttpUtility.UrlDecode(Request["fieldid"])

Esempio di esempio:

  • Livello controller:

    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));
    }
  • Livello cliente:

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

Nella funzione Documento pronto:

$(function () {     
  $("#btnsearch").click(function () {  
    $("#search-text").val(encodeURIComponent($("#search-text").val()));
    $("#search-form").submit();
  });
});

4
La tecnologia Jquery e lato client non ha nulla a che fare con MVC, la convalida avviene sul lato server con il framework MVC. Non è una risposta valida
diegosasw

1
Dato che Microsoft ignora letteralmente l'attributo AllowHtml e dato che l'unica soluzione praticabile lato server è sostituire la funzionalità del raccoglitore di modelli predefinito, direi che la codifica lato client è un'opzione perfettamente valida.
Jonathan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.