上传包含在 MVC 模型中的图像 [英] Upload image included in MVC model

查看:30
本文介绍了上传包含在 MVC 模型中的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下模型:

公开课照片{公共 int PhotoId { 获取;放;}公共字节[] ImageData { 获取;放;}公共日期时间日期上传{获取;放;}公共字符串 描述 { 获取;放;}public bool IsActive { 获取;放;}}

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

[HttpPost]公共 ActionResult 创建(WilhanWebsite.DomainClasses.Photo photo){如果(模型状态.IsValid){photo.DateUploaded = DateTime.Now;_context.Photos.Add(照片);_context.SaveChanges();return RedirectToAction("索引");}//我们只有在出现问题时才到这里返回视图(照片);}

我的观点如下:

@using (Html.BeginForm()){@Html.AntiForgeryToken()<div class="form-horizo​​ntal"><h4>照片</h4><小时/>@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 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 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 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 class="form-group"><div class="col-md-offset-2 col-md-10"><input type="submit" value="Create" class="btn btn-default"/>

}

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

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

解决方案

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

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

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

public HttpPostedFileBase UploadImages { get;放;}

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

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

您可能想要浏览 <代码>关注博文,以更好地熟悉 ASP.NET MVC 中文件上传工作的基础知识.我还写了一个这里有类似的答案,你可能会参考.

因此,一旦您在视图模型中添加带有 UploadImages 名称的 HttpPostedFileBase 属性,您就可以调整控制器动作以读取字节数组并将其存储在您的 ImageData 属性:

[HttpPost]公共 ActionResult 创建(WilhanWebsite.DomainClasses.Photo photo){如果(模型状态.IsValid){photo.DateUploaded = DateTime.Now;photo.ImageData = 新字节[photo.UploadImages.ContentLength];photo.UploadImages.Read(photo.ImageData, 0, photo.ImageData.Length);_context.Photos.Add(照片);_context.SaveChanges();return RedirectToAction("索引");}//我们只有在出现问题时才到这里返回视图(照片);}

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

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

I have the following model:

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

}

I would like the user to be able to enter the details for the photo then post the model the the controller. My controller action is as follows:

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

My view is as follows:

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

The view is displayed ok and allows the user to select a file from their local disk and enter the other model details. My problem is that although the model is posted to the controller ok, the Description, Date and IsActive flags are populated ok - the Image data is null.

Could anyone please let me know what I need to change so that the byte array for the photo is included in the model posted to the controller?

解决方案

The file input in your view has a name uploadImages. I can't see a property with this name in your view model. You seem to have some ImageData property which is a byte array, but there doesn't seem to be a corresponding input field with this name in your view.

This explains why you get null. You could make this work by respecting the convention. So for example if you intend to have such an input field in your view:

<input type="file" name="uploadImages" class="input-files" />

then make sure that you have a property on your view model with the same name. And of course of type HttpPostedFileBase.

public HttpPostedFileBase UploadImages { get; set; }

Also in your view make sure you are setting the proper content type of multipart/form-data:

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

You probably might want to go through the following blog post to better familiarize yourself with the basics of how uploading of files work in ASP.NET MVC. I've also written a similar answer here that you might consult.

So once you add the HttpPostedFileBase property with the UploadImages name in your view model you could adapt your controller action to read the byte array and store it your ImageData property:

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

Now bear in mind that this is an absolutely awful solution. Never do that in a real world application. In a correctly designed application you will have a view model that your controller action will take as a parameter. You're never gonna directly use your autogenerated EF model as parameter to your controller action. You will have a view model with the HttpPostedFileBase property which will be mapped to your domain model.

So in a properly designed application you will have a PhotoViewModel view model class that your controller action will take.

这篇关于上传包含在 MVC 模型中的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆