无法将带有list的viewmodel传递给controller-action(MVC 5)

时间:2016-03-30 12:58:33

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

我在传递包含"文件列表的视图模型时遇到问题"从我的视图到我的控制器(动作)。除了list(List Files)之外,viewmodel似乎被传递给具有所有propetries的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>
}

2 个答案:

答案 0 :(得分:0)

您的文件属于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。或者更简单地从模型中再次在控制器中重新填充文件集。

答案 1 :(得分:0)

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