[英]Getting Checkbox Value in ASP.NET MVC 4
我正在開發 ASP.NET MVC 4 應用程序。 這個應用程序有一個基本的形式。 我的表單的 model 如下所示:
public class MyModel
{
public string Name { get; set; }
public bool Remember { get; set; }
}
在我的表格中,我有以下 HTML。
<input id="Name" name="Name" type="text" value="@Model.Name" />
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
<label for="Remember"> Remember Me?</label>
當我發布表單時,model 中的 Remember 值始終為 false。 但是,model 中的 Name 屬性有一個值。 我通過在下面設置斷點來測試它:
[HttpPost]
public ActionResult MyAction(MyModel model)
{
Console.WriteLine(model.Remember.ToString());
}
我想不通。 為什么未設置 Checkbox 值?
@Html.EditorFor(x => x.Remember)
會產生:
<input id="Remember" type="checkbox" value="true" name="Remember" />
<input type="hidden" value="false" name="Remember" />
它是如何工作的:
checkbox
,則表單僅提交hidden
值(false) bool
屬性設置true
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
如果選中,它將始終發送默認值。
由於您使用Model.Name來設置值。 我假設您將空視圖模型傳遞給View。
因此,Remember的值為false,並將checkbox元素的值設置為false。 這意味着當您選擇復選框時,您將使用表單發布值“false”。 如果不選擇它,則不會發布,因此模型默認為false。 這就是為什么你在兩種情況下都看到了錯誤的價值。
只有在選中復選框時才會傳遞該值。 在Mvc中使用復選框
@Html.CheckBoxFor(x => x.Remember)
或者如果您不想將模型綁定到視圖。
@Html.CheckBox("Remember")
當沒有選擇時,Mvc會使用隱藏字段來保持值。
編輯,如果你真的厭惡這樣做,並希望自己生成元素,你可以做到。
<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked=\"checked\"" : "") />
僅使用此功能
$("input[type=checkbox]").change(function () {
if ($(this).prop("checked")) {
$(this).val(true);
} else {
$(this).val(false);
}
});
好的,復選框有點奇怪。 當您使用Html幫助程序時,它會在標記上生成兩個復選框輸入,如果選中它們,它們都將作為IEnumerable的名稱 - 值對傳入。
如果未在標記上檢查,則僅傳入值為false的隱藏輸入。
例如,在標記上你有:
@Html.CheckBox("Chbxs")
並在控制器操作中(確保名稱與控制器上的復選框參數名稱匹配):
public ActionResult Index(string param1, string param2,
string param3, IEnumerable<bool> Chbxs)
然后在控制器中你可以做一些像:
if (Chbxs != null && Chbxs.Count() == 2)
{
checkBoxOnMarkup = true;
}
else
{
checkBoxOnMarkup = false;
}
我知道這不是一個優雅的解決方案。 希望有人在這里可以提供一些指示。
代替
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
使用:
@Html.EditorFor(x => x.Remember)
這將為您提供專門用於記住的復選框
要將從表單中的復選框返回的值轉換為布爾屬性,我在自定義ModelBinder中使用構建轉換器中的ValueProviderResult。
ValueProviderResult cbValue = bindingContext.ValueProvider.GetValue("CheckBoxName");
bool value = (bool)cbValue.ConvertTo(typeof(bool));
我遇到了類似的問題,並且能夠通過使用復選框,hiddenfor和小JQuery來獲取復選框值,如下所示:
@Html.CheckBox("isPreferred", Model.IsPreferred)
@Html.HiddenFor(m => m.IsPreferred)
<script>
$("#isPreferred").change(function () {
$("#IsPreferred").val($("#isPreferred").val());
})
</script>
這是一個很大的痛苦,感覺應該更簡單。 這是我的設置和解決方案。
我正在使用以下HTML幫助器:
@Html.CheckBoxFor(model => model.ActiveFlag)
然后,在控制器中,我正在檢查表單集合並進行相應處理:
bool activeFlag = collection["ActiveFlag"] == "false" ? false : true;
[modelObject].ActiveFlag = activeFlag;
如果使用FormCollection而不是模型,則賦值可以如下所示:
MyModel.Remember = fields["Remember"] != "false";
@Html.EditorFor(x => x.ShowComment)
$(function () {
// set default value to control on document ready instead of 'on'/'off'
$("input[type='checkbox'][name='ShowComment']").val(@Model.ShowComment.ToString().ToLower());
});
$("#ShowComment").change(function() {
// this block sets value to checkbox control for "true" / "false"
var chkVal = $("input[type='checkbox'][name='ShowComment']").val();
if (chkVal == 'false') $("input[type='checkbox'][name='ShowComment']").val(true);
else $("input[type='checkbox'][name='ShowComment']").val(false);
});
對於使用Model的MVC。 模型:
public class UserInfo
{
public string UserID { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
}
HTML:
<input type="checkbox" value="true" id="checkbox1" name="RememberMe" checked="@Model.RememberMe"/>
<label for="checkbox1"></label>
在[HttpPost]函數中,我們可以獲得它的屬性。
[HttpPost]
public ActionResult Login(UserInfo user)
{
//...
return View(user);
}
我剛碰到這個(我不敢相信它不會打開/關閉!)
無論如何!
<input type="checkbox" name="checked" />
將發布“開”或“關”的值。
這個WONT綁定到一個布爾值,但你可以做這個愚蠢的解決方法!
public class MyViewModel
{
/// <summary>
/// This is a really dumb hack, because the form post sends "on" / "off"
/// </summary>
public enum Checkbox
{
on = 1,
off = 0
}
public string Name { get; set; }
public Checkbox Checked { get; set; }
}
對於具有相同名稱的多個復選框...刪除不必要的錯誤代碼:
List<string> d_taxe1 = new List<string>(Request.Form.GetValues("taxe1"));
d_taxe1 = form_checkbox.RemoveExtraFalseFromCheckbox(d_taxe1);
功能
public class form_checkbox
{
public static List<string> RemoveExtraFalseFromCheckbox(List<string> val)
{
List<string> d_taxe1_list = new List<string>(val);
int y = 0;
foreach (string cbox in val)
{
if (val[y] == "false")
{
if (y > 0)
{
if (val[y - 1] == "true")
{
d_taxe1_list[y] = "remove";
}
}
}
y++;
}
val = new List<string>(d_taxe1_list);
foreach (var del in d_taxe1_list)
if (del == "remove") val.Remove(del);
return val;
}
}
用它 :
int x = 0;
foreach (var detail in d_prix){
factured.taxe1 = (d_taxe1[x] == "true") ? true : false;
x++;
}
public ActionResult Index(string username, string password, string rememberMe)
{
if (!string.IsNullOrEmpty(username))
{
bool remember = bool.Parse(rememberMe);
//...
}
return View();
}
修改記住這樣
public class MyModel
{
public string Name { get; set; }
public bool? Remember { get; set; }
}
在控制器中使用可空的bool,並像這樣在null上回退為false
[HttpPost]
public ActionResult MyAction(MyModel model)
{
model.Remember = model.Remember ?? false;
Console.WriteLine(model.Remember.ToString());
}
在我的情況下,我沒有在get方法中設置模型屬性“Remember”。 檢查控制器中的邏輯。 你可能也在這樣做。 我希望這有幫助!
如果你真的想使用純HTML(無論出於何種原因)而不是內置的HtmlHelper擴展,你可以這樣做。
代替
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
嘗試使用
<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked" : "") />
HTML中的復選框輸入工作,以便在檢查時,它們發送值,當它們未被檢查時,它們根本不發送任何內容(這將導致ASP.NET MVC回退到默認值field, false
)。 此外,HTML中復選框的值可以是任何不僅是真/假的值,因此如果您真的想要,您甚至可以使用模型中字符串字段的復選框。
如果您使用內置的Html.RenderCheckbox
,它實際上輸出兩個輸入:復選框和隱藏字段,以便在取消選中復選框時發送錯誤值(不只是沒有)。 這可能會導致一些意外情況,例如:
我仔細閱讀了其他答案,並沒有完全開始工作 - 所以這就是我最終解決的問題。
我的表單使用Html.EditorFor(e => e.Property)
生成復選框,並在控制器中使用FormCollection
,它在控制器中傳遞字符串值'true,false'
。
當我處理結果時,我使用循環來循環它們 - 我還使用InfoProperty
實例來表示從表單中評估的當前模型值。
所以我只是檢查返回的字符串是否以單詞'true'
開頭,然后將boolean變量設置為true
並將其傳遞給返回模型。
if (KeyName.EndsWith("OnOff"))
{
// set on/off flags value to the model instance
bool keyTrueFalse = false;
if(values[KeyName].StartsWith("true"))
{
keyTrueFalse = true;
}
infoProperty.SetValue(processedInfo, keyTrueFalse);
}
瘋狂的想法......當傳遞給模型中的布爾時,Asp.Net MVC 應該只接受選中的復選框為“true”......。
我認為以下 - ModelBinder 接受 HTML 標准“開”意味着 true - 應該始終是 Asp.Net MVC 中的默認實現。 此解決方案適用於 Classic/Non-Core,但應該很容易適應 Core。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Brass9.Web.Mvc.ModelBinders
{
public class FixedCheckboxFormModelBinder : System.Web.Mvc.IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (
// Form POST
!controllerContext.HttpContext.Request.ContentType.StartsWith
("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)
/*
// Note: This is implied - by the way we add this ModelBinder to the global app list (typeof(bool))
||
bindingContext.ModelMetadata.ModelType != typeof(bool)
*/
)
{
return null;
}
string name = bindingContext.ModelName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(name);
if (valueProviderResult.AttemptedValue == "on")
{
var replacementResult = new ValueProviderResult(true, "on", System.Globalization.CultureInfo.CurrentCulture);
bindingContext.ModelState.SetModelValue(name, replacementResult);
return true;
}
return null;
}
}
}
然后在 Global.asax.cs 的Application_Start()
中啟用它:
ModelBinders.Binders.Add(typeof(bool), new Brass9.Web.Mvc.ModelBinders.FixedCheckboxFormModelBinder());
因此,我們只是構建了一個自定義 ModelBinder,僅針對 Model 值進行過濾,期望通過 POST 形式傳入布爾值,並向我們傳遞 HTML 標准“開啟”——安全地將其干預限制在復選框中。
嘗試應用此修復程序實際上有點奇怪,因為大多數關於 ModelBinders 的文檔都受到贊揚,但很少有清晰的操作方法。
為什么我們這樣解決:
我們正在遷移一個舊的應用程序以完全使用原始的 Asp.Net MVC(非核心)。 不僅將所有復選框移動到@Html.Checkbox...
(很多不是這樣寫的)需要很長時間,它還會產生很多不良結果,因為額外的、不必要的隱藏輸入,以及遷移頁面的難度。 例如,我們知道有些頁面有 Javascript 以特定順序遍歷 DOM 期望元素,隱藏的輸入會中斷,並且不想梳理每個頁面來尋找這些錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.