2

次のようにバインディングを使用して複数のファイルをアップロードViewsしています。ViewModel

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

        }

問題の説明 アップロードされたファイルのファイル拡張子が許可されていないタイプの場合に、それぞれの検証エラーに対して対応するエラーが表示されるように、これら 5 つのファイル アップロード入力コントロールのビュー モデルを定義するにはどうすればよいですか。5 つのファイル アップロード コントロールすべてに対してビュー モデル項目が 1 つしかありません。

ユーザーが許可されていない拡張子のファイルをアップロードしようとする代わりに、それぞれの検証エラーを表示するための複数のファイルアップロードコントロールのビューモデルを定義する最良の方法は何ですか?

4

1 に答える 1

2

ここでの本当の問題は、MVC には http ファイル用の適切なモデル バインダーがないことです。

したがって、mvc futures のような、ファイルのアップロードに関する特別なサポートを備えたプロジェクトを使用しない限り、自分で何かを汚して大変な作業をしなければなりません。

これは、あなたにとってもう少しうまくいくかもしれない例です。

まず、次のような 1 つのファイルを表す 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 です。これが複数のファイルをキャプチャする方法です (「ファイル」を使用した現在の実装では、1 つだけをキャプチャしています。

ページ レベル ビューへ:

@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 に答える