Вопрос по asp.net-mvc – Почему ASP.NET MVC Html.CheckBox выводит два входа с одинаковым именем?

30

Почему в мире делает линию:

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

результат в следующем HTML:

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

Теперь, когда я проверяю флажок и доступRequest.Form["ForSale"]Я получаю нелепый ответ"true,false", Я должен разобрать это?

Это скрытое поле не отображается для других элементов управления HtmlHelper, так почему оно используется для CheckBox?

How do I turn this stupid "feature" off? Или сделалHtmlHelper просто перерасти свою полезность?

Update

Из ответа ниже кажется, что за этим стоит некоторая логика. Я подготовил небольшой метод расширения, поэтому мне не нужно об этом думать (спасибо @ eu-ge-ne):

    public static bool GetCheckBoxValue(this System.Web.HttpRequestBase req, 
                                        string name) {
        return Convert.ToBoolean(req.Form.GetValues(name).First());
    }
Ну, это не ответ на ваш вопрос, почему :) Я бы предложил использовать связующее для моделей (то есть, что сказал Брэд). Matthew Groves
@mgroves возражают опубликовать ответ, чтобы сообщить мне, что я, вероятно, делаю неправильно? Frank Krueger
Почему бы вам просто не указать логическое значение в сигнатуре метода действия и позволить связыванию модели выполнить эту работу за вас? Brad Wilson
+1 - я только что столкнулся с этим вопросом на днях. Похоже, они пытались быть полезными, но в итоге раздражали тех из нас, кто действительно знает, как должны работать флажки. Eric Petroelje
Если вы используете Request.Form, вы, вероятно, делаете это неправильно. Matthew Groves

Ваш Ответ

7   ответов
38

Это заставляет поле быть включенным, если оно не проверено. Если вы снимите флажок, он не будет отправлен как часть страницы - он будет отправлен только в том случае, если он проверен, а затем будет установлено значение true. Скрытое поле гарантирует, что false будет отправлено, если флажок снят, поскольку скрытое поле всегда отправляется.

Чтобы развернуть: если ваша подпись метода действия похожа наpublic ActionResult b(bool b = false), то дополнительный генерируется<input/> не имеет значения. Если подпись вашего метода действияpublic ActionResult b(bool b = true) или жеpublic ActionResult b(bool b), затемb будет установленfalse если флажок включен, но не отмечен в определенной форме иb будет установленtrue или сгенерируйте ошибку, соответственно, в формах, где вы не включите флажок. этоHtml.CheckBox() поведение гарантирует, что & # x201C; unchecked & # x201D; всегда правильно отображается наfalse и что форма соответствует методу действия.
Так я должен разобрать строку? Frank Krueger
Вы не должны анализировать строку, а также не использовать объект Request непосредственно в своем действии: просто используйте логическое значение в качестве одного из параметров метода действия, и все будет обработано за вас.
2

Now whenever I check the box and access Request.Form["ForSale"], I get the ridiculous answer of "true,false". Am I supposed to parse that?

Попробуй это:

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

UPDATED:

What if in the next MVC build it will return the value in the revers order "false, true"? ... – 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);
@Frank Krueger - надеюсь, не в MVC2
Что, если в следующей сборке MVC он вернет значение в обратном порядке & quot; false, true & quot ;? Это работоспособное, но не надежное решение. Именно поэтому я отказался от встроенных помощников и сделал свой собственный.
0

пытаться

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

3

Я выбрал другой подход:

Не используйте вспомогательный метод Html.CheckBoxFor или Html.CheckBox для визуализации флажка, но визуализируйте его с использованием обычного HTML:

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

И я добавил скрипт jQuery, который устанавливает значение, когдаcheckbox проверено / не проверено.

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

Насколько я мог проверить это, кажется, что правильныйvalue всегда отправляется в контроллер, и больше никаких проблем с"true,false".

2

Если флажок не отмечен, он не будет включен в отправку формы. Так что это "особенность" дает вам результат для каждого CheckBox. Те, которые не отмечены, будут просто "ложными".

Я реализовал свои собственные вспомогательные функции CheckBox, которые работают по-разному. Большую часть времени я не хочу просто true или false, а просто набор значений отмеченных флажков. Он отлично подходит для выбора определенных элементов по их идентификатору, для которого необходимо выполнить действие. Я не хочу, чтобы пункты, не отмеченные галочкой, даже в списке.

Вы можете взглянуть на исходный код для расширений HTML и использовать аналогичную структуру для создания собственных методов CheckBox.

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

Я бы опубликовал свой, но я не использую стандартный класс HtmlHelper, так что это, вероятно, будет более запутанным. Я добавил параметр value в свои функции CheckBox, чтобы я мог использовать конкретное значение id вместо & quot; true & quot; или "ложь".

3

Вот как я это сделал в одном из моих приложений. Расстраивает, но, похоже, работает.

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

Надеюсь это поможет. Если у вас есть какие-либо дополнительные вопросы, просто оставьте комментарий, и я соответствующим образом обновлю свой ответ.

0

Я думаю, что самое чистое решение - это сделать:

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

Похожие вопросы