1. ホーム
  2. asp.net-mvc

[解決済み] MVC 3 ファイルアップロードとモデルバインディング

2023-03-24 01:45:48

質問

フォームからのアップロードはうまくいくのですが、データベースにモデル情報を渡して、もちろん違う名前でファイルを保存したいのです。

以下は私のRazorビューです。

@model CertispecWeb.Models.Container

@{
  ViewBag.Title = "AddDocuments";
}

<h2>AddDocuments</h2>

@Model.ContainerNo

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, 
            new { enctype = "multipart/form-data" }))
{
    <input type='file' name='file' id='file' />
    <input type="submit" value="submit" />
}

以下は私のControllerです。

[HttpPost]
public ActionResult Uploadfile(Container containers, HttpPostedFileBase file)
{
     if (file.ContentLength > 0)
     {
        var fileName = Path.GetFileName(file.FileName);
        var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"),
                       containers.ContainerNo);
        file.SaveAs(path);
     }

     return RedirectToAction("Index");
}

モデルの情報はコントローラには渡されません。モデルを更新する必要があるかもしれないと読みましたが、どのようにすればよいのでしょうか?

どのように解決するのですか?

フォームにはファイル以外の入力タグがないので、コントローラアクションではアップロードされたファイル以外のものを取得することはできません (サーバに送信されるのはこれだけです)。これを実現する一つの方法は、モデルの ID を含む hidden タグを含めることです。これにより、投稿先のコントローラアクション内でデータストアからモデルを取得することができます (ユーザがモデルを変更せず、単にファイルを添付することを想定している場合に、この方法を使用します)。

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.HiddenFor(x => x.Id)
    <input type="file" name="file" id="file" />
    <input type="submit" value="submit" />
}

を作成し、コントローラのアクションで

[HttpPost]
public ActionResult Uploadfile(int id, HttpPostedFileBase file)
{
    Containers containers = Repository.GetContainers(id);
    ...
}

一方、ユーザーがこのモデルを変更できるようにしたい場合は、サーバーに送信したいモデルの各フィールドに対して適切な入力フィールドを含める必要があります。

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(x => x.Prop1)
    @Html.TextBoxFor(x => x.Prop2)
    @Html.TextBoxFor(x => x.Prop3)
    <input type="file" name="file" id="file" />
    <input type="submit" value="submit" />
}

で、デフォルトのモデルバインダーがリクエストからこのモデルを再構築するようにします。

[HttpPost]
public ActionResult Uploadfile(Container containers, HttpPostedFileBase file)
{
    ...
}