У меня возникли проблемы с привязкой моей модели к ящику ввода, созданному пользовательским вспомогательным методом. Я завернул блок автозаполнения jquery ajax с помощью вспомогательного метода под названием «Html.AutoCompleteBoxAjax». Этот помощник в принципе просто создает элемент с функцией автозаполнения javascript.Невозможно связать свойство модели MVC с элементом ввода
Свойство в модели представляет собой строку под названием «formatName». Я проверил, что в сгенерированном html для представления оба имени и идентификатора входного элемента являются «formatName» и что нет других элементов с этими идентификаторами. Я также проверил, что модель имеет конструктор по умолчанию, и свойство "formatName" является общедоступным. Наконец, я подтвердил, что, когда модель канала передается в представление, значение 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>
Если вы являетесь предварительно заполняющими входами и другими элементами формы, то помощник должен правильно установить значение. Нет «после обработки», который позаботился об этом или о любом автоматическом процессе. Я бы рекомендовал вызывать встроенный помощник TextBox/TextBoxFor из вашего AutoCompleteBoxAjax и только предустановить для него параметры. – Jakub
О, конечно. Каким-то образом я понял, что причина, по которой помощники были определены как методы расширения, заключалась в том, чтобы сохранить какой-то механизм, с помощью которого связывалось волшебство. Очевидный в ретроспективе. Спасибо. – Gadzooks34