2009-07-14 10 views
30

Perché nel mondo fa la linea:Perché ASP.NET MVC Html.CheckBox emette due INPUT con lo stesso nome?

<%= Html.CheckBox("ForSale", Model.Product.ForSale)%> For Sale 

risultato nella seguente codice HTML:

<input id="ForSale" name="ForSale" type="checkbox" value="true" /> 
<input name="ForSale" type="hidden" value="false" /> 
For Sale 

Ora ogni volta che selezionare la casella e accesso Request.Form["ForSale"], ottengo la risposta ridicola di "true,false". Dovrei analizzarlo?

Questo campo nascosto non viene visualizzato per gli altri controlli HtmlHelper, quindi perché lo fa per CheckBox?

Come disattivare questa "funzione" stupida? Oppure il HtmlHelper ha perso la sua utilità?

Aggiornamento

Dalla risposta qui sotto, sembra che ci sia una logica dietro questo. Ho preparato un po 'di metodo di estensione in modo da non devo pensarci (grazie a @ eu-ge-ne):

public static bool GetCheckBoxValue(this System.Web.HttpRequestBase req, 
             string name) { 
     return Convert.ToBoolean(req.Form.GetValues(name).First()); 
    } 
+9

Se stai usando Request.Form, probabilmente stai sbagliando. –

+1

+1 - Mi sono imbattuto in questo problema anche l'altro giorno. Sembra che stessero cercando di essere d'aiuto, ma sono finiti per annoiare quelli di noi che sanno come funzionano le checkbox. –

+2

@mgroves mente inviando una risposta per farmi sapere cosa sto facendo probabilmente sto sbagliando? –

risposta

37

Costringe il campo da inserire se è incontrollato. Se deselezioni una casella di controllo non viene inviata come parte della pagina - vengono inviati solo se sono spuntati e quindi c'è un valore true. Il campo nascosto garantisce che il falso verrà inviato se la casella di controllo è deselezionata, poiché il campo nascosto viene sempre inviato.

+0

Quindi dovrei analizzare la stringa? –

+3

Non dovresti analizzare la stringa, né usare l'oggetto Request direttamente nella tua azione: usa solo un booleano come parametro del tuo metodo di azione e tutto sarà gestito per te – CodeClimber

+1

Per espandere: se la firma del metodo di azione è come 'public ActionResult b (bool b = false) ', quindi il' ' 'extra non fa differenza. Se la firma del metodo di azione è 'public ActionResult b (bool b = true)' o public ActionResult b (bool b) ', quindi' b' sarà impostato 'false' se la casella di controllo è inclusa ma deselezionata in un particolare modulo e 'b' verrà impostato' true' o genererà un errore, rispettivamente, su moduli in cui non è inclusa la casella di controllo. Questo comportamento 'Html.CheckBox()' assicura che "deselezionato" sia sempre mappato correttamente su 'false' e ​​che il modulo corrisponda al metodo di azione. – binki

2

Se un CheckBox non è selezionato, non sarà incluso nell'invio del modulo. Quindi questa "caratteristica" ti dà un risultato per ogni CheckBox. Quelli che non sono controllati saranno semplicemente "falsi".

Ho implementato le mie proprie funzioni di assistente CheckBox che funzionano in modo diverso. La maggior parte delle volte non voglio solo vero o falso, ma solo una raccolta dei valori delle caselle spuntate. È fantastico per selezionare determinati elementi dal loro id su cui eseguire un'azione. Non voglio gli elementi non controllati nemmeno nella lista.

È possibile dare un'occhiata al codice sorgente per le estensioni html e utilizzare una struttura simile per creare i propri metodi CheckBox.

http://aspnet.codeplex.com/sourcecontrol/changeset/view/23011?projectName=aspnet#288010

avrei post la mia, ma non sto utilizzando la classe HtmlHelper standard, quindi sarebbe probabilmente più confusa. Ho aggiunto un parametro value alle mie funzioni CheckBox in modo da poter utilizzare un valore id specifico anziché "true" o "false".

2

Ora ogni volta che spunta la casella e accedo a Request.Form ["ForSale"], ottengo la ridicola risposta di "vero, falso". Dovrei analizzarlo?

Prova questo:

var ForSale = Convert.ToBoolean(Request.Form.GetValues("ForSale").First()); 

aggiornamento:

E se nel prossimo MVC costruirla restituirà il valore nei revers ordine "falso, vero"? ...- Mastermind

var ForSale = Request.Form.GetValues("ForSale") 
    .Select(x => x.ToUpperInvariant()).Contains("TRUE"); 

// or 

// FormatException can be thrown from Convert.ToBoolean() 
var ForSale = Request.Form.GetValues("ForSale") 
    .Select(x => Convert.ToBoolean(x)).Contains(true); 
+0

Cosa succede se nel prossimo build MVC restituirà il valore nell'ordine inverso "false, true"? È una soluzione praticabile ma non affidabile. È per questo che ho abbandonato gli helper integrati e ho fatto il mio. – User

+1

@Frank Krueger - spero non in MVC2 –

3

Ecco come ho fatto in una delle mie applicazioni. Frustrante, ma sembra funzionare.

public virtual ActionResult Edit(int id, FormCollection values) 
{ 
    SomeObject dbData = _repository.GetSomeObject(id); 

    try 
    { 
     UpdateModel(dbData); 
     if (values.GetValues("CheckBoxId").Contains("true")) 
      dbData.SomeBooleanProperty = true; 
     else 
      dbData.SomeBooleanProperty = false; 

     _repository.Save(); 

     Session["Success"] = "Successfully edited the part."; 
     return RedirectToAction("Index"); 
    } 
    catch 
    { 
     // Handle validation errors here 
     return View(new SomeObjectFormViewModel(dbData)); 
    } 
} 

Spero che questo aiuti. Se hai delle domande di follow-up, lascia un commento e aggiornerò la mia risposta di conseguenza.

0

provare

request.form["chkBoxes"].replace("false","").split(new char[] {','}, stringsplitoptions.removeemptyentries);

0

Penso che la soluzione più pulita è quella di fare:

(bool)formCollection["key"].ConvertTo(typeof(bool)) 
3

ho preso un approccio diverso:

Non utilizzare il Html.CheckBoxFor o HTML. Metodo di supporto CheckBox per il rendering di una casella di controllo, ma renderlo utilizzando normale html:

<input id="ShowOther" name="ShowOther" value="<%=Model.ShowOther %>" type="checkbox" <% if (Model.ShowOther) { %>checked="checked"<% } %> /> 

E ho aggiunto uno script jQuery che imposta il valore quando la casella di controllo è selezionata/deselezionata.

<script type="text/javascript"> 
    $(function() { 
     $('#ShowOther').click(function() { 
      var checked = $(this).attr('checked'); 
      if (checked != undefined) 
       $(this).val(true); 
      else 
       $(this).val(false); 
     }); 
    }); 
</script> 

Per quanto ho potuto testare questo, sembra che il corretto valore di viene sempre inviato al controller, e non più problemi con "vero, falso".

Problemi correlati