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

时间:2013-04-18 19:36:09

标签: c# asp.net-mvc model-binding

我无法将模型绑定到自定义帮助器方法创建的输入框。我用一个名为“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')
    });

视图的相关部分

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

1 个答案:

答案 0 :(得分:1)

来自@Jakub的回答结果很简单。帮助者本身必须填充该值; html助手没有自动绑定。一旦我处理了这个,帖子的自动绑定回到控制器按预期工作。