我无法让我的模型绑定到由自定义帮助方法创建的输入框。我用一个名为“Html.AutoCompleteBoxAjax”的辅助方法包装了一个 jquery ajax 驱动的自动完成框。这个助手基本上只是创建一个带有 javascript 自动完成功能的元素。
模型中的属性是一个名为“formatName”的字符串。我已经验证,在为视图生成的 html 中,输入元素的名称和 id 都是“formatName”,并且没有其他具有这些身份的元素。我还检查了模型是否具有默认构造函数,并且“formatName”属性是可公开访问的。最后,我验证了当 Channel 模型被传递到视图中时,Channel.formatName 具有正确的值。然而,尽管如此,我无法获得绑定到元素的值,并且输入框保持空白。反过来,从视图到控制器也没有绑定,Channel.formatName 保持空白。
我错过了什么?是不是因为我使用了自定义辅助方法?
模型:
namespace WebApp.Models
{
public class ChannelModel
{
XYZ.DataAccess.ODS.DB db = Config.DB();
public string id { get; set; }
// Parent Project
[Display(Name = "Project")]
public string projectID { get; set; }
// Format Name
[Required(ErrorMessage = "Format is required.")]
[RegularExpression(Constants.username_regex, ErrorMessage = Constants.username_regexErrorMsg)]
[Display(Name = "Format")]
public string formatName { get; set; }
// Channel Name
[Required(ErrorMessage="Channel name is required.")]
[StringLength(100, ErrorMessage = Constants.minLengthErrorMsg, MinimumLength = Constants.username_minLength)]
[RegularExpression(Constants.username_regex, ErrorMessage = Constants.username_regexErrorMsg)]
[Display(Name = "Channel name")]
public string name { get; set; }
// Sequence
[Display(Name = "Sequence")]
public string sequenceID { get; set; }
public ChannelModel()
{
id = Guid.NewGuid().ToString();
}
public ChannelModel(XYZ.DataAccess.ODS.Channel channel_db)
{
id = channel_db.id;
projectID = channel_db.project_id;
name = channel_db.name;
formatName = channel_db.format_name;
sequenceID = channel_db.sequence_id;
}
public XYZ.DataAccess.ODS.Channel buildDBObject()
{
XYZ.DataAccess.ODS.Channel channel = new XYZ.DataAccess.ODS.Channel();
channel.id = id;
channel.project_id = projectID;
channel.name = name;
channel.format_name = formatName;
channel.sequence_id = sequenceID;
return channel;
}
}
}
看法
@model WebApp.Models.ChannelModel
@using HelperMethods.Infrastructure
@{
ViewBag.Title = "Edit";
var sequences = ViewData["sequences"] as List<SelectListItem>;
}
<h2>Edit</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@section header {
}
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Channel</legend>
@Html.HiddenFor(model => model.id)
@Html.HiddenFor(model => model.projectID)
@Html.HiddenFor(model => model.name)
<div class="editor-field">
@Html.LabelFor(model => model.name):
@Html.DisplayFor(model => model.name)
</div>
<div class="editor-label">
@Html.Label("Format")
</div>
<div class="editor-field">
@Html.AutoCompleteBoxAjax("formatName", Url.Action("GetFormatsBeginningWith"))
@Html.ValidationMessageFor(model => model.formatName)
</div>
<!-- SEQUENCE -->
<div class="editor-label">
@Html.Label("Sequence")
</div>
<div class="editor-field">
@Html.SlaveDropdownList("sequenceID", "groupID", Url.Action("GetSequencesInGroup"), WebApp.Util.makeSelectList(sequences, Model.sequenceID))
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
控制器
namespace WebApp.Controllers
{
public class ChannelController : Infrastructure.NoCacheController
{
XYZ.DataAccess.ODS.DB db = Config.DB();
-- stuff --
[HttpGet]
public ActionResult GetFormatsBeginningWith(string term)
{
var formats = db.getFormatsBeginningWith(term);
List<CustomHelpers.AutocompleteItem> items = new List<CustomHelpers.AutocompleteItem>();
foreach (var format in formats)
items.Add(new CustomHelpers.AutocompleteItem { value = format.name, label = format.name });
var j = Json(items, JsonRequestBehavior.AllowGet);
return j;
}
public ActionResult Edit(string id)
{
ChannelModel channelModel = new ChannelModel(db.getChannel(id));
string groupID = db.getProject(channelModel.projectID).group_id;
var sequences = db.getSequencesInGroup(groupID);
ViewData["sequences"] = makeSelectListItems(sequences);
return View(channelModel);
}
//
// POST: /Channel/Edit/5
[HttpPost]
public ActionResult Edit(ChannelModel model)
{
if (ModelState.IsValid)
{
db.updateChannel(model.buildDBObject());
return RedirectToAction("Index");
}
string groupID = db.getProject(model.projectID).group_id;
var sequences = db.getSequencesInGroup(groupID);
ViewData["sequences"] = makeSelectListItems(sequences);
return View(model);
}
-- more stuff --
}
}
AutoCompleteBox 的辅助方法
public static MvcHtmlString AutoCompleteBoxAjax(this HtmlHelper html, string id, string actionUrl)
{
TagBuilder input = new TagBuilder("input");
input.Attributes.Add("id", id);
input.Attributes.Add("name", id);
input.Attributes.Add("type", "text");
input.AddCssClass("autocomplete_ajax");
input.Attributes.Add("value", "");
input.Attributes.Add("action", actionUrl);
var variables = new Dictionary<string, string>() {
{"AUTOCOMPLETE_ID", id}
};
var script = populateScriptTemplate("TEMPLATE_autocomplete_ajax.js", variables);
StringBuilder s = new StringBuilder();
s.AppendLine(input.ToString(TagRenderMode.SelfClosing));
s.AppendLine(script);
return new MvcHtmlString(s.ToString());
}
用于自动完成的 Javascript
$('#AUTOCOMPLETE_ID').autocomplete({
source: $('#AUTOCOMPLETE_ID').attr('action')
});
视图 html 的相关部分
<div class="editor-field">
<input action="/Channel/GetFormatsBeginningWith" class="autocomplete_ajax" id="formatName" name="formatName" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="formatName" data-valmsg-replace="true"></span>
</div>