查看模型在asp.net mvc 3中的多个文件上传 [英] view model for multiple file upload in asp.net mvc 3

查看:197
本文介绍了查看模型在asp.net mvc 3中的多个文件上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个文件上传视图与视图模型绑定如下

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

< div class =field fullwidth>
< label for =text-input-normal>
@ Html.Label(选择活动日期时间)< / label>
< input type =textid =activevalue =@ DateTime.Now/>
@ Html.ValidationMessageFor(model => model.ActiveDateTime)
< / div>

< div class =field fullwidth>
< label>
@ Html.Label(选择语言)
< / label>
@ Html.DropDownList(Language,(SelectList)ViewBag.lang)
< / div>

< div class =field>
< label>
@ Html.Label(一般新闻)
< / 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(体育新闻)
< / 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(商业新闻)
< / 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(国际新闻)
< / 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 =submitclass =bt bluevalue =Submit/>
< / footer>



$ b

使用数据注释查看模型,以验证允许的扩展名的文件上传,如下所示:> > / p>

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

// public IEnumerable< SelectListItem>语言{get;组; }
$ b [File(AllowedFileExtensions = new string [] {.jpg,.gif,.tiff,.png,.pdf,.wav}, MaxContentLength = 1024 * 1024 * 8,ErrorMessage =无效文件)]
public HttpPostedFileBase files {get;组; }

$ b

控制器如果错误存在,则返回多个文件并返回视图

$ $ $ $ $ $ $ $ $ $ $ $ $ public ActionResult Index(UploadNewsModel news,IEnumerable< HttpPostedFileBase> ;文件)
{
if(ModelState.IsValid)
{
foreach(文件中的文件)
{
if(file!= null& amp; ;& 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);




$ b

问题解释 strong>
如何为这五个文件上传输入控件定义视图模型,以便在不允许输入文件的文件扩展名的情况下,针对相应的验证错误显示相应的错误。我只有一个查看所有五个文件上传控制的模型项目。


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

p>

所以除非你使用mvc futures这样的项目,在文件上传的时候有一些额外的支持,否则你将不得不得到一些肮脏的并且努力工作的东西。 >

以下是一个可能对您有用的示例。

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

  public class FileViewModel 
{
public Guid Id {get;组; }
public string Name {get;组; }
public bool删除{get;组; }
public string ExistingUrl {get;组; }

public HttpPostedFileBase FileBase {get;组; }
}

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



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

  public class IndexViewModel 
{
public IList< FileViewModel>文件{get;组; }
}

这里重要的是文件的IList,这就是我们如何捕获多个文件(在当前的文件实现中,您只能捕获一个文件)。
$ b

在页面级别视图上:

  @model IndexViewModel 
@ Html.ValidationSummary(true)
@ Html.EditorFor(x => x.Files)
< input type =submitvalue = Submit/>
< / form>

,我们接下来要做的就是为这个时候应该使用的 FileViewModel 创建一个EditorTemplate 。


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

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

请注意 ViewData.TemplateInfo.HtmlFieldPrefix 的使用情况,就像我说的这是因为mvc对文件输入类型的支持不佳。我们必须自己做。我们除了每个文件的名字都像'[0] .FileBase'等。
$ b

这将正确地填充 FileViewModel POST动作。

到目前为止,验证过程如何?

再次,您可以手动执行服务器。自己测试文件扩展名,只需使用以下命令将错误添加到模型中即可:

  ModelState.AddModelError( ,无效的扩展名。)

另外一个说明,扩展验证应该在客户端(以及服务器端)

I have multiple file upload views with view model binding as following

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

View model with data annotation for validating file upload for allowed extension as follows:

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

}

Controller: for saving multiple file and return view if error is exist

  [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);
            }

        }

Problem explaination How do I define view model for those five file upload input control so that corresponding error is shown for respective validation error if file extension of file uploaded is not allowed type. I have only one view model items for all five file upload control.

What can be best way to define view model for those multiple file upload control for showing respective validation error instead user try to upload file of unallowed extension???

解决方案

The real problem here is that MVC doesn't have a decent model binder for http files.

So unless you use a project like mvc futures which has some extra support around file uploads you are going to have to get some what dirty and do the hard work yourself.

Here is an example that might work a bit better for you.

Firstly I would create a ViewModel to represent one file something like this:

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

Obviously properties depend on your requirements, the important bit is the FileBase and that it is its own model.

Next, a ViewModel for your page (UploadNewsModel in your case):

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

The important bit here is the IList of Files, this is how we capture multiple files (in your current implementation with 'file' you are only capturing one.

Onto the page level view:

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

Note the EditorFor, what we will do next is create a EditorTemplate for the FileViewModel which should be used at this point.

Like this:

@model FileViewModel

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

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

Note the usage of ViewData.TemplateInfo.HtmlFieldPrefix, it kinda sucks but like I said this is because of the poor mvc support for the file input type. We have to do it ourselves. We except the name for each file to be something like '[0].FileBase' etc.

This will populate the FileViewModel correctly on the POST action.

So far so good, what about validation?

Well again you can do that manually on the server. Test the file extensions yourself, and simply use the following to add the error to the model like:

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

On another note, extension validation should be done on the client side (and as well as on the server side)

这篇关于查看模型在asp.net mvc 3中的多个文件上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆