【问题标题】:Cannot pass viewmodel with list to controller-action (MVC 5)无法将带有列表的视图模型传递给控制器​​操作(MVC 5)
【发布时间】:2016-07-18 12:03:18
【问题描述】:

我在将包含“文件”列表的视图模型从我的视图传递到我的控制器(操作)时遇到问题。除了列表(列表文件)之外,视图模型似乎与所有属性一起传递给了 actionresult。即使模型在我提交表单时包含文件,该列表仍然保持为空。

我做错了什么?我将从我的控制器、模型、视图模型和我的 RazorHTML 中粘贴我的 c# 代码。

文件模型:

public class File
{
    [Key]
    public int ID { get; set; }
    [Display(Name = "Filnamn")]
    public string Filename { get; set; }
    //[Display(Name = "Beskrivning")]
    //public string Description { get; set; }
    [Display(Name = "Filtyp")]
    public string ContentType { get; set; }
    public byte[] Data { get; set; }
    public int Size { get; set; }

    //public string CreatorId { get; set; }

    public string CreatorID { get; set; }
    [Required]
    [Display(Name = "Skapare")]
    [ForeignKey("CreatorID")]
    public virtual ApplicationUser Creator { get; set; }

    //public int DocumentId { get; set; }

    public int DocumentID { get; set; }
    [Required]
    [Display(Name = "Dokument")]
    [ForeignKey("DocumentID")]
    public virtual Document Document { get; set; }
}

视图模型:

public class CreateDocumentViewModel
{
    public CreateDocumentViewModel()
    {
        CheckboxUsers = new List<CheckBoxListUser>();
        CheckboxGroups = new List<CheckBoxListGroup>();
        CheckboxTags = new List<CheckBoxListTags>();
        Files = new List<File>();
    }

    [Display(Name = "Beskrivning")]
    public string Description { get; set; }
    [Display(Name = "Titel")]
    public string Name { get; set; }
    [DataType(DataType.MultilineText)]
    [Display(Name = "Markdown")]
    public string Markdown { get; set; }
    HttpPostedFileBase FileToAdd { get; set; }

    [Display(Name="Användare")]
    public List<CheckBoxListUser> CheckboxUsers { get; set; }
    [Display(Name = "Grupper")]
    public List<CheckBoxListGroup> CheckboxGroups { get; set; }
    [Display(Name = "Taggar")]
    public List<CheckBoxListTags> CheckboxTags { get; set; }
    [Display(Name = "Filer")]
    public ICollection<File> Files { get; set; }
    public string FilesJson { get; set; }
}

查看:

    @model MarkdownManagerNew.Viewmodels.CreateDocumentViewModel

@{
    ViewBag.Title = "CreateDocument";
}

<h2>Nytt dokument</h2>


@Html.BeginForm("CreateFile", "User", new { model = Model, test = Model.Name, files = Model.Files }, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        <div class="col-md-10">
            @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control", placeholder = "Titel" } })
            @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-10">
            @Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control", placeholder = "Beskrivning" } })
            @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="row">
        <div class="col-sm-12">
            <div class="form-group col-md-6 markdownEditorForm">
                <div class="col-md-12">
                    @Html.EditorFor(model => model.Markdown, new { htmlAttributes = new { @class = "form-control markdownEditor" } })
                    @Html.ValidationMessageFor(model => model.Markdown, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="col-sm-6 markdownResult"></div>
        </div>
    </div>

    <div class="row">
        <dl class="dl-horizontal">
            <dt>
                @Html.DisplayNameFor(model => model.CheckboxGroups)
            </dt>

            @for (int i = 0; i < Model.CheckboxGroups.Count; i++)
            {
                <dd>
                    @Html.CheckBoxFor(x => x.CheckboxGroups[i].IsChecked)
                    @Html.HiddenFor(x => x.CheckboxGroups[i].ID)
                    @Html.HiddenFor(x => x.CheckboxGroups[i].Display)

                    @Html.DisplayFor(x => x.CheckboxGroups[i].Display)
                </dd>
            }


            <dt>
                @Html.DisplayNameFor(model => model.CheckboxUsers)
            </dt>

            @for (int i = 0; i < Model.CheckboxUsers.Count; i++)
            {
                <dd>
                    @Html.CheckBoxFor(x => x.CheckboxUsers[i].IsChecked)
                    @Html.HiddenFor(x => x.CheckboxUsers[i].ID)
                    @Html.HiddenFor(x => x.CheckboxUsers[i].Display)

                    @Html.DisplayFor(x => x.CheckboxUsers[i].Display)
                </dd>
            }

            <dt>
                @Html.DisplayNameFor(model => model.CheckboxTags)
            </dt>

            @for (int i = 0; i < Model.CheckboxTags.Count; i++)
            {
                <dd>
                    @Html.CheckBoxFor(x => x.CheckboxTags[i].IsChecked)
                    @Html.HiddenFor(x => x.CheckboxTags[i].ID)
                    @Html.HiddenFor(x => x.CheckboxTags[i].Display)

                    @Html.DisplayFor(x => x.CheckboxTags[i].Display)
                </dd>
            }

        </dl>
    </div>

    <div class="form-group">
        @Html.Label("File", new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <input type="file" id="File" name="upload" />
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Ladda upp fil" class="btn btn-default" />
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-10">
            @if (Model.Files.Count > 0)
            {
                <h3>@Html.DisplayNameFor(model => model.Files)</h3>
                <table class="table table-striped table-bordered">
                    <tr>
                        <th>Filename</th>
                        <th>Filetype</th>
                        <th>Size(bytes)</th>
                    </tr>

                    @foreach (var file in Model.Files)
                    {
                        <tr>
                            <td>@file.Filename</td>
                            <td>@file.ContentType</td>
                            <td>@file.Size</td>
                        </tr>
                    }

                </table>
            }
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-1 col-md-10">
            <input type="submit" value="Skapa" class="btn btn-default" />
        </div>
    </div>
</div>


<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

控制器

[HttpPost]
    public ActionResult CreateFile(CreateDocumentViewModel viewModel)
    {
        var file = repo.CreateFile(upload, GetCurrentUser());
        viewModel.Files.Add(file);
        TempData["viewModel"] = viewModel;

        //return RedirectToAction("CreateDocument", file);
        return RedirectToAction("CreateDocument", new { files = viewModel.Files });

    }

-编辑-

我还尝试为每个文件中的每个属性添加编辑器字段,如下所示:

@for (int i = 0; i < Model.Files.Count; i++)
{
    <div>

        @Html.LabelFor(x => x.Files[i].DocumentID)
        @Html.EditorFor(x => x.Files[i].DocumentID)
        @Html.ValidationMessageFor(x => x.Files[i].DocumentID)
        @Html.LabelFor(x => x.Files[i].CreatorID)
        @Html.EditorFor(x => x.Files[i].CreatorID)
        @Html.ValidationMessageFor(x => x.Files[i].CreatorID)
        @Html.LabelFor(x => x.Files[i].ID)
        @Html.EditorFor(x => x.Files[i].ID)
        @Html.ValidationMessageFor(x => x.Files[i].ID)
        @Html.LabelFor(x => x.Files[i].ContentType)
        @Html.EditorFor(x => x.Files[i].ContentType)
        @Html.ValidationMessageFor(x => x.Files[i].ContentType)
        @Html.LabelFor(x => x.Files[i].CreatorID)
        @Html.EditorFor(x => x.Files[i].CreatorID)
        @Html.ValidationMessageFor(x => x.Files[i].CreatorID)
        @Html.LabelFor(x => x.Files[i].Data)
        @Html.EditorFor(x => x.Files[i].Data)
        @Html.ValidationMessageFor(x => x.Files[i].Data)
        @Html.LabelFor(x => x.Files[i].Filename)
        @Html.EditorFor(x => x.Files[i].Filename)
        @Html.ValidationMessageFor(x => x.Files[i].Filename)
        @Html.LabelFor(x => x.Files[i].Size)
        @Html.EditorFor(x => x.Files[i].Size)
        @Html.ValidationMessageFor(x => x.Files[i].Size)
    </div>
}

【问题讨论】:

    标签: c# asp.net-mvc razor model asp.net-mvc-5


    【解决方案1】:

    您的文件属于 ICollection 类型,因此每个文件信息都需要存在于表单中,以便能够在填充的视图模型中发布到控制器。目前,您没有此集合的字段,因此 ICollection 在发布到控制器时为空。您可以创建自定义 EditorFor 来显示文件数据以及将此数据发布到控制器。

    请参阅本教程了解如何执行此操作:

    http://blog.learningtree.com/en/editing-collections-in-asp-net-mvc/

    在您的代码中,您正在为复选框做类似的事情:

    @for (int i = 0; i < Model.CheckboxUsers.Count; i++)
    {
        <dd>
            @Html.CheckBoxFor(x => x.CheckboxUsers[i].IsChecked)
            @Html.HiddenFor(x => x.CheckboxUsers[i].ID)
            @Html.HiddenFor(x => x.CheckboxUsers[i].Display)
    
            @Html.DisplayFor(x => x.CheckboxUsers[i].Display)
        </dd>
    }
    

    注意隐藏字段,这是将数据传递给控制器​​以获取复选框列表的内容。我建议为这些文件创建一个自定义 EditorFor。或者更简单地从模型中再次在控制器中重新填充文件集合。

    【讨论】:

    • 我尝试为每个文件中的每个属性添加编辑字段。但文件似乎仍然没有传递到控制器。
    【解决方案2】:

    但是 Files 集合不在任何输入中。它们基本上只是标签,因此它们不会发布到服务器。由于它们不会由用户更改,因此您可以在操作中再次从数据库加载文件。

    【讨论】:

    • 啊,我明白了。但这些文件尚不存在于数据库中。您可以选择将文件上传到临时文档。然后创建包含文件的文档。只有这样文件才会存在于数据库中。如何使文件成为输入的一部分,以便与模型一起传递?我试过做一个隐藏的输入但没有成功。也许我做错了?
    • 好像你在问另一个问题,我不清楚它是什么。
    猜你喜欢
    • 2016-07-24
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-12-27
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多