MVC没有从模型中

时间:2017-03-17 14:48:21

标签: asp.net-mvc

任何人都可以告诉我为什么,如果我的模型清楚地表明我的价值观是“真实”或“虚假”MVC仍然认为它说“真,假”。我认为这是因为它使Request与我的模型混淆;但是,我明确告诉它使用模型。

enter image description here

如上图所示,模型值为“true”。但是,在下图中,它认为值是“真,假”。我怎样才能使用“true?”

enter image description here

模型

public class TagCategorySearchViewModel
{
    public long Id { get; set; }

    public string Name { get; set; }

    public List<TagSearchViewModel> Tags { get; set; }
}

public class TagSearchViewModel
{
    public long Id { get; set; }

    public string Name { get; set; }

    public bool IsSelected { get; set; }
}

控制器

    [Authorize]
    public ActionResult FilterPrereqGrid(EditStudentPrerequisitesViewModel model, int page = 1)
    {
        model.Prerequisites = new List<PrerequisiteListViewModel>();
        var businessPartner = _bpManager.GetBusinessPartnerByMapGuid(model.BusinessPartnerMapGuid);

        model.Prerequisites.AddRange(_epManager.GetFullPrerequisitesLeftJoinedWithExperience(model.ExperienceId, businessPartner?.Id));

        // fix for how MVC binds checkboxes... it send "true,false" instead of just true, so we need to just get the true
        for (int i = 0; i < model.TagCategories?.Count(); i++)
        {
            for (int j = 0; j < model.TagCategories[i].Tags?.Count(); j++)
            {
                model.TagCategories[i].Tags[j].IsSelected = bool.Parse((Request.QueryString[$"TagCategories[{i}].Tags[{j}].IsSelected"] ?? "false").Split(',')[0]);
            }
        }

        var selectedTagIds = model.TagCategories?.SelectMany(x => x.Tags).Where(x => x.IsSelected == true).Select(x => x.Id).ToArray();

        // filter by selected tags
        if (selectedTagIds.Any())
        {
            model.Prerequisites = (from p in model.Prerequisites
                                   let prereqTagIds = p.Prerequisite.PrerequisiteTags.Select(et => et.TagId)
                                   where selectedTagIds.All(x => prereqTagIds.Contains(x))
                                   select p).ToList();
        }

        model.Prerequisites = (from m in model.Prerequisites
                               let ownerDocs = _deManager.GetDocumentsByOwnerAndSourceId(model.BusinessPartnerMapGuid, m.Prerequisite.Id).OrderByDescending(e => e.CreatedDate)
                               select new PrerequisiteListViewModel
                               {
                                   Prerequisite = m.Prerequisite,
                                   Selected = m.Selected,
                                   Mandatory = m.Mandatory,
                                   HasExpiration = m.Prerequisite.HasExpiration,
                                   BusinessExpirationPeriod = m.Prerequisite.ExpirationPeriod == 0 ? "None" : m.Prerequisite.ExpirationPeriod.ToString(),
                                   DocOwnerGuid = (ownerDocs.Any() ? model.BusinessPartnerMapGuid : Guid.Empty),
                                   DocRowGuid = (ownerDocs.Any() ? ownerDocs.First().DocRowguid : Guid.Empty),
                                   HasDocuments = ownerDocs.Any()
                               }).ToList();

        int rowsPerPage = 1;

        model.TotalRecords = model.Prerequisites.Count();
        model.Prerequisites = model.Prerequisites.Skip(page * rowsPerPage - rowsPerPage).Take(rowsPerPage).ToList();

        return PartialView("~/Views/BusinessExperience/_EditPrerequisites.cshtml", model);
    }

2 个答案:

答案 0 :(得分:2)

这是设计上的。 Html.CheckBoxFor扩展程序实际上呈现如下内容:

<input type="checkbox" .. />
<input type="hidden" />

因此,这两个都与您渲染的属性具有相同的名称。选中后,复选框返回&#34; True&#34;,但如果未选中,则复选框不返回任何内容。这是复选框与表单帖子一起使用的方式。为了确定没有检查任何内容,MVC框架包含一个隐藏字段,以便返回&#34; False&#34;什么时候不检查,但是&#34;真,假&#34;检查时(因为具有相同名称的多个项目从表单帖子以这种方式返回)。然后MVC模型绑定转换&#34; True,False&#34;为真。

您可以使用值true呈现自己的<input type="checkbox" />,并且只返回true,但如果未选中,则不会呈现任何内容。请注意......

答案 1 :(得分:0)

这实际上有效,遗憾的是我不能只做明显的方式而且必须写出这一切!

@model List<Prep2PracticeWeb.Models.ViewModels.TagCategorySearchViewModel>

@if (Model != null)
{
    <div class="tag-categories">
        @for (int i = 0; i < Model.Count(); i++)
        {
            @Html.HiddenFor(x => Model[i].Id)
            @Html.HiddenFor(x => Model[i].Name)
            <h4 data-toggle="collapse" data-target="#CollapsableTagCategory_@Model[i].Id" aria-expanded="false" aria-controls="CollapsableTagCategory_@Model[i].Id">
                <span class="glyphicon glyphicon-chevron-right"></span>
                <span class="glyphicon glyphicon-chevron-down"></span>
                @Model[i].Name
            </h4>
                            <div id="CollapsableTagCategory_@Model[i].Id" class="tag-container collapse">
                                @if (Model[i].Tags != null)
                                {
                                    for (int j = 0; j < Model[i].Tags.Count(); j++)
                                    {
                                        @Html.HiddenFor(x => Model[i].Tags[j].Id)
                                        @Html.HiddenFor(x => Model[i].Tags[j].Name)
                                        @* the following commented out line won't work because MVC is funny *@
                                        @*<label>@Html.CheckBoxFor(x => Model[i].Tags[j].IsSelected) @Model[i].Tags[j].Name</label>*@
                                        <label>
                                            <input @(Model[i].Tags[j].IsSelected ? @"checked=""checked""" : string.Empty) data-val="true" data-val-required="The IsSelected field is required." id="TagCategories_@(i)__Tags_@(j)__IsSelected" name="TagCategories[@i].Tags[@j].IsSelected" type="checkbox" value="true"> @Model[i].Tags[j].Name
                                            <input name="TagCategories[@i].Tags[@j].IsSelected" type="hidden" value="false">
                                        </label>
                                    }
                                }
                            </div>
        }
    </div>
}

更新:我意识到GET在这种情况下不是一个合适的策略,因为查询字符串只能在服务器返回500错误之前很久。我切换到POST,这缓解了这个问题。