Это работает очень хорошо, используя пользовательский механизм связывания моделей и обычный HTML ...
Во-первых, ваша HTML-форма в синтаксисе Razor:
@using (Html.BeginForm("Action", "Controller", FormMethod.Post)) {
<ol>
<li><input type="textbox" name="tBox" value="example of another form element" /></li>
<li><input type="checkbox" name="cBox" value="1" /> One</li>
<li><input type="checkbox" name="cBox" value="2" /> Two</li>
<li><input type="checkbox" name="cBox" value="3" /> Three</li>
<li><input type="checkbox" name="cBox" value="4" /> Four</li>
<li><input type="checkbox" name="cBox" value="5" /> Five</li>
<li><input type="submit" /></li>
</ol>
}
(FormMethod.Post
также может быть .Get
, не имеет значения для этого)
Тогда в собственном смысле MVC есть объект модели, который представляет отправку вашей формы:
public class CheckboxListExampleModel {
public string TextboxValue { get; set; }
public List<int> CheckboxValues { get; set; }
}
И собственный класс связующего элемента модели (мне нравитсячтобы поместить это в привязываемую модель, я повторю созданную выше модель, чтобы показать, куда я ее добавлю. Размещение внутри нее также позволяет связующему использовать установщики приватных свойств, что хорошо):
public class CheckboxListExampleModel {
public string TextboxValue { get; private set; }
public List<int> CheckboxValues { get; private set; }
public class Binder : DefaultModelBinder {
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
var model = new CheckboxListExampleModel();
model.TextboxValue = bindingContext.GetValueAsString("tBox");
string checkboxCsv = bindingContext.GetValueAsString("cBox");
// checkboxCsv will be a comma-separated list of the 'value' attributes
// of all the checkboxes with name "cBox" which were checked
model.CheckboxValues = checkboxCsv.SplitCsv<int>();
return model;
}
}
}
.GetValueAsString()
- это метод расширения, используемый для ясности, вот он:
public static string GetValueAsString(this ModelBindingContext context, string formValueName, bool treatWhitespaceAsNull = true) {
var providerResult = context.ValueProvider.GetValue(formValueName);
if (providerResult.IsNotNull() && !providerResult.AttemptedValue.IsNull()) {
if (treatWhitespaceAsNull && providerResult.AttemptedValue.IsNullOrWhiteSpace()) {
return null;
} else {
return providerResult.AttemptedValue.Trim();
}
}
return null;
}
.SplitCsv<T>()
- это также метод расширения, но он достаточно распространенНужен и достаточно грязный код, который я оставлю читателю в качестве упражнения.
И, наконец, ваше действие по обработке формы:
[HttpPost]
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) {
// stuff
}