私は次のモデルを持っています:
public class Photo
{
public int PhotoId { get; set; }
public byte[] ImageData { get; set; }
public DateTime DateUploaded { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
}
ユーザーが写真の詳細を入力して、モデルをコントローラーに投稿できるようにしたいと考えています。私のコントローラーのアクションは次のとおりです:
[HttpPost]
public ActionResult Create(WilhanWebsite.DomainClasses.Photo photo)
{
if (ModelState.IsValid)
{
photo.DateUploaded = DateTime.Now;
_context.Photos.Add(photo);
_context.SaveChanges();
return RedirectToAction("Index");
}
//we only get here if there was a problem
return View(photo);
}
私の見解は次のとおりです。
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Photo</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.ImageData, new { @class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="uploadImages" class="input-files" />
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.DateUploaded, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.DateUploaded)
@Html.ValidationMessageFor(model => model.DateUploaded)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.IsActive, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.IsActive)
@Html.ValidationMessageFor(model => model.IsActive)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
ビューは問題なく表示され、ユーザーはローカルディスクからファイルを選択して、他のモデルの詳細を入力できます。私の問題は、モデルはコントローラーにポストされても問題ないが、説明、日付、およびIsActiveフラグが問題なく設定されていることです-画像データがnullです。
写真のバイト配列がコントローラーに投稿されたモデルに含まれるように、何を変更する必要があるかを誰かに教えてもらえますか?
ビューに入力されたファイルの名前はuploadImages
です。この名前のプロパティがビューモデルに表示されません。バイト配列であるいくつかのImageData
プロパティを持っているようですが、ビューにこの名前の対応する入力フィールドがないようです。
これは、nullになる理由を説明しています。慣習を尊重することで、この作業を行うことができます。たとえば、ビューにそのような入力フィールドを含めるつもりなら、
<input type="file" name="uploadImages" class="input-files" />
次に、ビューモデルに同じ名前のプロパティがあることを確認します。そしてもちろんHttpPostedFileBase
型です。
public HttpPostedFileBase UploadImages { get; set; }
また、ビューでmultipart/form-data
の適切なコンテンツタイプを設定していることを確認してください:
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
}
following blog post
を確認して、ASP.NET MVCでファイルのアップロードがどのように機能するかの基本をよく理解することをお勧めします。また、参考になるかもしれない similar answer here
も書きました。
したがって、ビューモデルでHttpPostedFileBase
プロパティにUploadImages
の名前を追加すると、コントローラーアクションを調整してバイト配列を読み取り、ImageData
プロパティに保存できます。
[HttpPost]
public ActionResult Create(WilhanWebsite.DomainClasses.Photo photo)
{
if (ModelState.IsValid)
{
photo.DateUploaded = DateTime.Now;
photo.ImageData = new byte[photo.UploadImages.ContentLength];
photo.UploadImages.Read(photo.ImageData, 0, photo.ImageData.Length);
_context.Photos.Add(photo);
_context.SaveChanges();
return RedirectToAction("Index");
}
//we only get here if there was a problem
return View(photo);
}
これは絶対にひどい解決策であることを覚えておいてください。実際のアプリケーションでは、これを行わないでください。正しく設計されたアプリケーションでは、コントローラーアクションがパラメーターとしてとるビューモデルがあります。自動生成されたEFモデルをコントローラーアクションのパラメーターとして直接使用することは決してありません。ドメインモデルにマップされるHttpPostedFileBase
プロパティを持つビューモデルが作成されます。
したがって、適切に設計されたアプリケーションには、コントローラーアクションが実行するPhotoViewModel
ビューモデルクラスがあります。
この行を変更します。
@using (Html.BeginForm())
これに:
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
次に変更します。
<input type="file" name="uploadImages" class="input-files" />
に:
<input type="file" name="ImageData" class="input-files" />
次に、この行を変更します。
public byte[] ImageData { get; set; }
これに:
public HttpPostedFileBase ImageData { get; set; }
最後に、次のようなコードを使用して、画像をバイト配列に読み込みます。
var bs = new byte[ImageData.ContentLength];
using (var fs = ImageData.InputStream)
{
var offset = 0;
do
{
offset += fs.Read(bs, offset, bs.Length - offset);
} while (offset < bs.Length);
}
見る:
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
<input type="file" id="ImageFile" name="ImageFile" .../>
...
}
コントローラ:
[HttpPost]
public ActionResult Create(Photo photo, HttpPostedFileBase ImageFile)
{
byte[] buf = new byte[ImageFile.ContentLength];
ImageFile.InputStream.Read(buf, 0, buf.Length);
photo.ImageData = buf;
...
}