2

我有多个文件上传ViewsViewModel绑定如下:

@model IVRControlPanel.Models.UploadNewsModel
  @using (Html.BeginForm("index", "NewsUpload", FormMethod.Post, new { name = "form1", @id = "form1" }))
        {
            @Html.ValidationSummary(true)

            <div class="field fullwidth">
                <label for="text-input-normal">
                    @Html.Label("Select Active Date Time")</label>
                <input type="text" id="active" value="@DateTime.Now" />
                 @Html.ValidationMessageFor(model => model.ActiveDateTime)
            </div>

            <div class="field fullwidth">
                <label>
                    @Html.Label("Select Language")
                </label>
                @Html.DropDownList("Language", (SelectList)ViewBag.lang)
            </div>

            <div class="field">
                <label>
                    @Html.Label("General News")
                </label>
               @Html.TextBoxFor(model => model.generalnews, new { name = "files", @class="custom-file-input", type = "file" })
                @Html.ValidationMessageFor(model => model.generalnews)
            </div>
            <div class="field">
                <label>
                    @Html.Label("Sports News")
                </label>
               @Html.TextBoxFor(model => model.sportsnews, new { name = "files", @class = "custom-file-input", type = "file" })
                @Html.ValidationMessageFor(model => model.sportsnews)
            </div>         
            <div class="field">
                <label>
                    @Html.Label("Business News")
                </label>
               @Html.TextBoxFor(model => model.businessnews, new { name = "files", @class = "custom-file-input", type = "file" })
                @Html.ValidationMessageFor(model => model.businessnews)
            </div>            
            <div class="field">
                <label>
                    @Html.Label("International News")
                </label>
               @Html.TextBoxFor(model => model.internationalnews, new { name = "files", @class = "custom-file-input", type = "file" })
                @Html.ValidationMessageFor(model => model.internationalnews)
            </div>    
             <div class="field">
                <label>
                    @Html.Label("Entertaintment News")
                </label>
               @Html.TextBoxFor(model => model.entertaintmentnews, new { name = "files", @class = "custom-file-input", type = "file" })
                @Html.ValidationMessageFor(model => model.entertaintmentnews)
            </div>          

             <footer class="pane">
                <input type="submit" class="bt blue" value="Submit" />
            </footer>                              
        }

带有数据注释的视图模型,用于验证允许扩展的文件上传,如下所示:

 public class UploadNewsModel
{
    public DateTime ActiveDateTime { get; set; }

   // public IEnumerable<SelectListItem> Language { get; set; }

    [File(AllowedFileExtensions = new string[] { ".jpg", ".gif", ".tiff", ".png", ".pdf", ".wav" }, MaxContentLength = 1024 * 1024 * 8, ErrorMessage = "Invalid File")]
    public HttpPostedFileBase files { get; set; }

}

控制器:用于保存多个文件并在存在错误时返回视图

  [HttpPost]
            public ActionResult Index(UploadNewsModel news, IEnumerable<HttpPostedFileBase> files)
            {
                if (ModelState.IsValid)
                {
                    foreach (var file in files)
                    {
                        if (file != null && file.ContentLength > 0)
                        {
                            var fileName = Path.GetFileName(file.FileName);
                            var serverpath = Server.MapPath("~/App_Data/uploads/News");
                            var path = Path.Combine(serverpath, fileName);
                            if (!Directory.Exists(serverpath))
                            {
                                Directory.CreateDirectory(serverpath);
                            }

                            file.SaveAs(path);
                        }

                    }
                }
                return View(news);
            }

        }

问题说明 如何为这五个文件上传输入控件定义视图模型,以便在不允许上传文件的文件扩展名类型时显示相应的错误以显示相应的验证错误。对于所有五个文件上传控件,我只有一个视图模型项。

为那些显示各自验证错误的多个文件上传控件定义视图模型的最佳方法是什么,而不是用户尝试上传不允许扩展名的文件???

4

1 回答 1

2

这里真正的问题是 MVC 没有合适的 http 文件模型绑定器。

因此,除非您使用像 mvc futures 这样的项目,它对文件上传有一些额外的支持,否则您将不得不自己做一些肮脏的工作。

这是一个可能更适合您的示例。

首先,我将创建一个 ViewModel 来表示一个文件,如下所示:

public class FileViewModel
{  
    public Guid Id { get; set; }
    public string Name { get; set; }
    public bool Delete { get; set; }
    public string ExistingUrl { get; set; }

    public HttpPostedFileBase FileBase { get; set; }
}

显然属性取决于您的要求,重要的是 FileBase 并且它是它自己的模型。

接下来,您的页面的 ViewModel(在您的情况下为 UploadNewsModel):

public class IndexViewModel
{ 
    public IList<FileViewModel> Files { get; set; }
}

这里重要的一点是文件的 IList,这就是我们捕获多个文件的方式(在您当前使用 'file' 的实现中,您只捕获一个。

进入页面级视图:

@model IndexViewModel
<form method="post" action="@Url.Action("Index")" enctype="multipart/form-data">
@Html.ValidationSummary(true)
@Html.EditorFor(x => x.Files)
<input type="submit" value="Submit" />
</form>

注意EditorFor,我们接下来要做的是为FileViewModel创建一个EditorTemplate ,此时应该使用它。

像这样:

@model FileViewModel

<h4>@Model.Name</h4>
@Html.HiddenFor(x => x.Id)
@Html.CheckBoxFor(x => x.Delete)

<input @( "name=" + ViewData.TemplateInfo.HtmlFieldPrefix + ".FileBase") type="file" />

注意ViewData.TemplateInfo.HtmlFieldPrefix的使用,它有点糟糕,但就像我说的那样,这是因为文件输入类型的 mvc 支持很差。我们必须自己做。我们将每个文件的名称除外,例如“[0].FileBase”等。

这将在 POST 操作中正确填充FileViewModel 。

到目前为止一切顺利,验证呢?

好吧,您可以在服务器上手动执行此操作。自己测试文件扩展名,然后简单地使用以下内容将错误添加到模型中,例如:

ModelState.AddModelError("","Invalid extension.")

另一方面,扩展验证应该在客户端(以及服务器端)完成

于 2012-08-29T04:00:33.197 回答