我無法讓模型綁定到由自定義幫助程序方法創建的輸入框。我用一個名爲「Html.AutoCompleteBoxAjax」的助手方法包裝了一個jquery ajax驅動的自動完成框。這個助手基本上只是創建一個具有JavaScript自動完成功能的元素。無法將MVC模型屬性綁定到輸入元素
模型中的屬性是一個名爲「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 Helper方法
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>
當您預先填充輸入和其他表單元素時,助手的職責是正確設置值。沒有「後處理」來處理這個或任何自動過程。我建議從你的AutoCompleteBoxAjax中調用一個內置的TextBox/TextBoxFor幫助器,並且只爲它預先填充參數。 – Jakub
哦,當然。不知何故,我已經知道幫助者被定義爲擴展方法的原因是爲了保留一些神奇發生的綁定機制。回想起來很明顯。謝謝。 – Gadzooks34