上传MVC模型中包含的图像

Rob*_*man 15 asp.net-mvc post image bytearray

我有以下型号:

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

}
Run Code Online (Sandbox Code Playgroud)

我希望用户能够输入照片的详细信息,然后将模型发布到控制器.我的控制器动作如下:

[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);
    }
Run Code Online (Sandbox Code Playgroud)

我的观点如下:

@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>
}
Run Code Online (Sandbox Code Playgroud)

视图显示正常,允许用户从其本地磁盘中选择文件并输入其他模型详细信息.我的问题是虽然模型发布到控制器ok,但是描述,日期和IsActive标志填充正确 - 图像数据为空.

任何人都可以让我知道我需要更改什么,以便照片的字节数组包含在发布到控制器的模型中?

Dar*_*rov 25

视图中的文件输入具有名称uploadImages.我在视图模型中看不到具有此名称的属性.您似乎有一些ImageData属性是字节数组,但在您的视图中似乎没有具有此名称的相应输入字段.

这解释了为什么你得到null.您可以通过尊重惯例来完成这项工作.例如,如果您打算在视图中包含这样的输入字段:

<input type="file" name="uploadImages" class="input-files" />
Run Code Online (Sandbox Code Playgroud)

然后确保您的视图模型上具有相同名称的属性.当然还有类型HttpPostedFileBase.

public HttpPostedFileBase UploadImages { get; set; }
Run Code Online (Sandbox Code Playgroud)

同样在您的视图中,请确保您正在设置正确的内容类型multipart/form-data:

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

您可能希望通过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);
}
Run Code Online (Sandbox Code Playgroud)

现在请记住,这是一个绝对可怕的解决方案.永远不要在现实世界的应用程序中这样做 在正确设计的应用程序中,您将拥有一个视图模型,您的控制器操作将将其作为参数.您永远不会直接使用自动生成的EF模型作为控制器操作的参数.您将拥有一个包含该HttpPostedFileBase属性的视图模型,该属性将映射到您的域模型.

因此,在设计合理的应用程序中,您将拥有一个PhotoViewModel控制器操作将采用的视图模型类.