web-dev-qa-db-ja.com

MVC:ファイルアップロードと他のフォームフィールドを1つのアクションに投稿する方法

ライブラリ内の各区画のサムネイル画像をアップロードする必要があるDocumentControllerを使用してドキュメントライブラリアプリケーションを作成しています。ファイルアップロードフィールドを、他のフィールド(タイトル、説明、CategoryIdなど)と同じ作成/編集フォームに保持したい。
問題は、フォームタグを組み合わせたりネストしたりできるかどうかわからないことです。

Html.BeginForm("Create", "Document", FormMethod.Post, enctype = "multipart/form-data")

そして

Html.BeginForm()

私の見解は次のとおりです。

 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Publications.WebUI.Models.DocumentEditViewModel >" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <fieldset>
        <legend>Edit
            <%=  Html.Truncate(Model.Document.Title, 50)%></legend>
        <%= Html.ValidationSummary(false) %>
        <% using (Html.BeginForm())
           { %>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.Title) %>
        </div>
        <div class="editor-field">
            <%= Html.HiddenFor(model => model.Document.DocumentId ) %>
            <%= Html.ValidationMessageFor(model => model.Document.Title) %>
            <%= Html.TextBoxFor(model => model.Document.Title)%>
        </div>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.DocumentUrl)%>
        </div>
        <div class="editor-field">
            <%= Html.ValidationMessageFor(model => model.Document.DocumentUrl)%>
            <%= Html.TextBoxFor(model => model.Document.DocumentUrl)%>
        </div>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.Description)%>
        </div>
        <div class="editor-field">
            <%= Html.ValidationMessageFor(model => model.Document.Description)%>
            <%= Html.TextAreaFor(model => model.Document.Description) %>
        </div>
        <div class="editor-label">
            <%= Html.LabelFor(model => model.Document.ThumbnailUrl )%>
        </div>
        <div class="editor-field">
            <% using (Html.BeginForm("Create", "Document",
                    FormMethod.Post, new { enctype = "multipart/form-data" }))
               {%>
            <%= Html.ValidationMessageFor(model => model.Document.ThumbnailUrl )%>
            <input name="uploadFile" type="file" />
            <% } %>
        </div>
        <div class="formActions">
            <div class="backNav">
                <%= Html.ActionLink("< Back to List", "Index") %>
            </div>
            <div class="submit">
                <input type="submit" value="Save" />
            </div>
            <% } %>
        </div>
    </fieldset>
</asp:Content>

私のコントローラーは、ドキュメントモデルとHttpPostedFileBaseを取得し、ファイルをサーバーにアップロードして、ドキュメントをリポジトリに保存しようとします。

 [HttpPost]
 public ActionResult Create(Document document, HttpPostedFileBase uploadFile)
 {

     if (ModelState.IsValid)
     {
         //Process file upload
         //Update repository

      }

       return View("List");
  }

だから、同じアクションでファイルのアップロードとリポジトリの更新が可能かどうか、これを容易にするためにビューをどのように構成する必要があるのか​​疑問に思っています。

34
Brendan

Steve Sandersonの素晴らしい本(Pro ASP.NET MVC 2 Framework)を見て、彼のSports Storeサンプルアプリケーションには、ファイルアップロードフォーム「multipart/form-data」要素と混合した標準フォーム要素があります。そのため、ページ上のすべてのフォーム要素にはマルチパート型で十分です。アップロードされた画像はdbに保存されていますが、同じアクション内でfile.SaveAs()を実行できると確信しています。サンダーソンさん、ありがとう。あなたのコードの複製を気にしないでください...

[〜#〜] view [〜#〜]

    <asp:Content ContentPlaceHolderID="MainContent" runat="server">
    <h1>Edit <%= Model.Name %></h1>

    <% using (Html.BeginForm("Edit", "Admin", FormMethod.Post, 
                             new { enctype = "multipart/form-data" })) { %>
        <%= Html.Hidden("ProductID") %>
        <p>
            Name: <%= Html.TextBox("Name") %>
            <div><%= Html.ValidationMessage("Name") %></div>
        </p>
        <p>
            Description: <%= Html.TextArea("Description", null, 4, 20, null) %>
            <div><%= Html.ValidationMessage("Description") %></div>
        </p>
        <p>
            Price: <%= Html.TextBox("Price") %>
            <div><%= Html.ValidationMessage("Price") %></div>
        </p>
<p>
    Category: <%= Html.TextBox("Category") %>
    <div><%= Html.ValidationMessage("Category") %></div>
</p>
<p>
    Image:
    <% if(Model.ImageData == null) { %>
        None
    <% } else { %>
        <img src="<%= Url.Action("GetImage", "Products", 
                                 new { Model.ProductID }) %>" />
    <% } %>
    <div>Upload new image: <input type="file" name="Image" /></div>                
</p>

<input type="submit" value="Save" /> &nbsp;&nbsp;
        <%=Html.ActionLink("Cancel and return to List", "Index") %>
    <% } %>
</asp:Content>

[〜#〜] controller [〜#〜]

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Product product, HttpPostedFileBase image)
    {
        if (ModelState.IsValid) {
            if (image != null) {
                product.ImageMimeType = image.ContentType;
                product.ImageData = new byte[image.ContentLength];
                image.InputStream.Read(product.ImageData, 0, image.ContentLength);
            }
            productsRepository.SaveProduct(product);
            TempData["message"] = product.Name + " has been saved.";
            return RedirectToAction("Index");
        }
        else // Validation error, so redisplay same view
            return View(product);
    }
36
Brendan