在我的ASP.NET MVC应用程序中,我使用以下代码呈现复选框:
<%= Html.CheckBoxFor(i=>i.ReceiveRSVPNotifications) %>
现在,我看到这会使同时复选框输入标记和隐藏的输入标记。我遇到的问题是当我尝试使用FormCollection从复选框中检索值时:
FormValues["ReceiveRSVPNotifications"]
我得到的值是“true,false”。查看呈现的HTML时,我可以看到以下内容:
<input id="ReceiveRSVPNotifications" name="ReceiveRSVPNotifications" value="true" type="checkbox">
<input name="ReceiveRSVPNotifications" value="false" type="hidden">
因此,FormValues集合似乎加入了这两个值,因为它们具有相同的名称。
任何想法?
答案 0 :(得分:168)
看看这里:
http://forums.asp.net/t/1314753.aspx
这不是一个bug,实际上与Ruby相同的方法 使用Rails和MonoRail。
当您提交带有复选框的表单时,仅在以下情况下发布该值 选中该复选框。所以,如果你不选中复选框,那么 在很多情况下你都不会将任何内容发送到服务器 希望错误发送。由于隐藏输入具有相同的名称 作为复选框,如果未选中该复选框,您仍然会得到一个 'false'发送到服务器。
选中该复选框后,ModelBinder将自动获取 关心从'true,false'中提取'true'
答案 1 :(得分:17)
我和肖恩(上图)有同样的问题。这种方法对于POST来说可能很棒,但对于GET来说真的很糟糕。因此,我实现了一个简单的Html扩展,它只是将隐藏的字段拉出来。
public static MvcHtmlString BasicCheckBoxFor<T>(this HtmlHelper<T> html,
Expression<Func<T, bool>> expression,
object htmlAttributes = null)
{
var result = html.CheckBoxFor(expression).ToString();
const string pattern = @"<input name=""[^""]+"" type=""hidden"" value=""false"" />";
var single = Regex.Replace(result, pattern, "");
return MvcHtmlString.Create(single);
}
我现在遇到的问题是我不希望更改MVC框架来破坏我的代码。所以我必须确保我有解释这份新合同的测试报道。
答案 2 :(得分:14)
我使用这种替代方法来呈现GET表单的复选框:
/// <summary>
/// Renders checkbox as one input (normal Html.CheckBoxFor renders two inputs: checkbox and hidden)
/// </summary>
public static MvcHtmlString BasicCheckBoxFor<T>(this HtmlHelper<T> html, Expression<Func<T, bool>> expression, object htmlAttributes = null)
{
var tag = new TagBuilder("input");
tag.Attributes["type"] = "checkbox";
tag.Attributes["id"] = html.IdFor(expression).ToString();
tag.Attributes["name"] = html.NameFor(expression).ToString();
tag.Attributes["value"] = "true";
// set the "checked" attribute if true
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
if (metadata.Model != null)
{
bool modelChecked;
if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
{
if (modelChecked)
{
tag.Attributes["checked"] = "checked";
}
}
}
// merge custom attributes
tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
var tagString = tag.ToString(TagRenderMode.SelfClosing);
return MvcHtmlString.Create(tagString);
}
它类似于 Chris Kemp 的方法,它正常工作,除了这个不使用基础{{1} }和CheckBoxFor
。它基于原始Regex.Replace
方法的来源。
答案 3 :(得分:10)
Here is the source code用于附加输入标记。微软非常友好地包含了准确解决这个问题的评论。
if (inputType == InputType.CheckBox)
{
// Render an additional <input type="hidden".../> for checkboxes. This
// addresses scenarios where unchecked checkboxes are not sent in the request.
// Sending a hidden input makes it possible to know that the checkbox was present
// on the page when the request was submitted.
StringBuilder inputItemBuilder = new StringBuilder();
inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
TagBuilder hiddenInput = new TagBuilder("input");
hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
hiddenInput.MergeAttribute("name", fullName);
hiddenInput.MergeAttribute("value", "false");
inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
return MvcHtmlString.Create(inputItemBuilder.ToString());
}
答案 4 :(得分:7)
我认为最简单的解决方案是直接渲染INPUT元素:
<input type="checkbox"
id="<%=Html.IdFor(i => i.ReceiveRSVPNotifications)%>"
name="<%=Html.NameFor(i => i.ReceiveRSVPNotifications)%>"
value="true"
checked="<%=Model.ReceiveRSVPNotifications ? "checked" : String.Empty %>" />
在Razor语法中,它更容易,因为&#39;检查&#39;属性直接使用&#34;检查&#34;给予“真实”的价值。服务器端值。