简体   繁体   English

无法将MVC模型属性绑定到输入元素

[英]Unable to bind MVC model property to input element

I'm having trouble getting my model to bind to an input box created by a custom helper method. 我无法让我的模型绑定到由自定义帮助程序方法创建的输入框。 I wrapped a jquery ajax-driven autocomplete box with a helper method called "Html.AutoCompleteBoxAjax." 我用一个名为“ Html.AutoCompleteBoxAjax”的帮助器方法包装了一个由jQuery ajax驱动的自动完成框。 This helper basically just creates an element with javascript autocomplete functionality. 该帮助程序基本上只是创建一个具有javascript自动完成功能的元素。

The property in the model is a string called "formatName". 模型中的属性是一个名为“ formatName”的字符串。 I have verified that, in the generated html for the view, both the name and id of the input element are "formatName", and that there are no other elements with those identities. 我已验证,在为视图生成的html中,输入元素的名称和ID均为“ formatName”,并且没有其他具有这些标识的元素。 I've also checked that the model has a default constructor, and that the "formatName" property is publicly accessible. 我还检查了模型是否具有默认构造函数,以及“ formatName”属性是否可公开访问。 Lastly, I've verified that when the Channel model is passed into the view, Channel.formatName has the correct value. 最后,我已验证将Channel模型传递到视图中时,Channel.formatName具有正确的值。 Yet despite all this, I can't get the value to bind to the element, and the input box remains blank. 尽管如此,我还是无法将值绑定到元素,并且输入框仍为空白。 There is also no binding when going the other way, from view to controller, and Channel.formatName remains blank. 从视图到控制器的另一种选择也没有绑定,并且Channel.formatName保持空白。

What am I missing? 我想念什么? Is it somehow because I'm using a custom helper method? 是因为我正在使用自定义帮助程序方法吗?

Model: 模型:

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


}

View 视图

@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>

Controller 调节器

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

Helper method for AutoCompleteBox 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 for the autocomplete 自动完成的Javascript

$('#AUTOCOMPLETE_ID').autocomplete({
    source: $('#AUTOCOMPLETE_ID').attr('action')
    });

Relevant portion of the view's html 视图的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>

Answer turned out to be simple with input from @Jakub. 使用@Jakub的输入,答案很简单。 The helper itself has to populate the value; 助手本身必须填充值。 there's no automatic binding that takes place for html helpers. html帮助程序没有自动绑定。 Once I took care of this, the auto binding of posts back to the controller worked as expected. 一旦我解决了这个问题,自动将帖子自动绑定回控制器就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM