我正在从部分共享视图中加载产品图像,我正在尝试使用上一个问题中建议的Ifrom文件。
所以在我的产品控制器中,我有以下方法
修改
我只想保存文件在数据库中的路径,然后将文件保存在磁盘上,这是实现此目的的正确方法。
public ActionResult FileUpload(ProductImages model)
{
if (model.Image != null)
{
var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
var filePath = Path.Combine(uploads, GetUniqueName(model.Image.FileName));
model.Image.CopyTo(new FileStream(filePath, FileMode.Create));
}
// to do : Return something
return RedirectToAction("Index", "Home");
}
我的产品图片类
public class ProductImages
{
[Key]
public int ProductImageId { get; set; }
public int ProductID { get; set; }
public string ProductImageTitle { get; set; }
public string ProductImageUploadUrl { get; set; }
public string ProductImageRealPath { get; set; }
public string ServerIpAddress { get; set; }
public string ProductImageAltTag { get; set; }
public int DisplayOrder { get; set; }
public IFormFile Image { set; get; }
}
我正在通过以下方式加载我的共享布局。
<div class="tab-pane" id="images">
Product Images
@await Html.PartialAsync("_ProductPicture", Model)
</div>
这是我的共享视图的代码我认为我对我声明IFormFile的方式做错了
@model solitude.models.ProductImages
<div class="form-group">
<form asp-action="FileUpload" enctype="multipart/form-data">
<input asp-for="ImageCaption" />
<input asp-for="ImageDescription" />
<input asp-for="MyImage" />
<input type="submit" />
</form>
</div>
我收到以下错误
AggregateException:发生了一个或多个错误。 (属性'ProductImages.Image'是一个接口类型('IFormFile')。如果是 导航属性手动配置此关系 通过将其强制转换为映射的实体类型,否则忽略该属性 属性使用'[NotMapped]'属性或使用 'OnModelCreating'中的'EntityTypeBuilder.Ignore'。) System.Threading.Tasks.Task.ThrowIfExceptional(布尔 includeTaskCanceledExceptions)
InvalidOperationException:属性'ProductImages.Image'属于 接口类型('IFormFile')。如果它是手动导航属性 通过将此属性强制转换为映射来配置此属性的关系 实体类型,否则使用'[NotMapped]'忽略该属性 属性或在'OnModelCreating'中使用'EntityTypeBuilder.Ignore'。
修改2
[HttpPost]
public ActionResult FileUpload(ProductImageVm model)
{
if (model.Image != null)
{
var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
var fileId = GetUniqueName(model.Image.FileName);
var filePath = Path.Combine(uploads, fileId);
model.Image.CopyTo(new FileStream(filePath, FileMode.Create));
// to do : Save the record in ProductImage table
var pi = new ProductImages { ProductID = model.ProductId };
pi.ProductImageTitle = model.Title;
pi.ProductImageRealPath = fileId; //Storing the fileId
_context.ProductImages.Add(pi);
_context.SaveChanges();
}
return RedirectToAction("Index", "Home");
}
现在我在另一个表单中加载表单的一件事可能是问题
答案 0 :(得分:2)
您不应在实体类中使用IFormFile
type属性。根据注释,您希望将图像存储在磁盘中,并将路径存储到表中的图像。所以只需从实体类定义中删除public IFormFile Image { set; get; }
属性。
您可以在视图模型中使用IFormFile
,该模型用于在视图和操作方法之间传输数据。因此,从视图
public class ProductImageVm
{
public int ProductId { set;get;}
public string Title { set;get;}
public IFormFile Image { set; get; }
//Add other properties AS NEEDED by your view
}
现在要上传产品56的图像,创建此视图模型的对象,将ProductId设置为56并发送到GET操作中的视图。在视图中,我们将productId保存在隐藏的表单字段中,当我们需要保存新的ProductImages
实体记录时,可以在HttpPost操作中稍后使用该字段。
public IActionResult UploadImage(int productId)
{
var vm = new ProductImageVm { ProductId=productId};
return View(vm);
}
和视图,它是我们的视图模型的强类型
@model ProductImageVm
<form asp-action="FileUpload" asp-controller="Products" method="post"
enctype="multipart/form-data">
<input asp-for="Title" />
<input asp-for="ProductId" type="hidden" />
<input asp-for="Image" />
<input type="submit" />
</form>
现在,在您的HttpPost操作方法中,使用与参数相同的视图模型,读取Image
属性并将其保存到磁盘并将路径存储在表中。您不需要存储完整路径。您可以存储相对路径。在下面的示例中,我在保存ProductImages实体记录时将唯一文件Id(文件名)存储到ProductImageRealPath
属性值。
[HttpPost]
public ActionResult FileUpload(ProductImageVm model)
{
if (model.Image != null)
{
var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
var fileId = GetUniqueName(model.Image.FileName);
var filePath = Path.Combine(uploads,fileId);
model.Image.CopyTo(new FileStream(filePath, FileMode.Create));
}
// to do : Save the record in ProductImage table
var pi=new ProductImages { ProductId = model.ProductId};
pi.ProductImageTitle = model.Title;
pi.ProductImageRealPath = fileId; //Storing the fileId
db.ProductImages.Add(pi);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}