在asp.net core 2.0 MVC中注册用户后,我希望能够上传pdf文件并将其名称或Id保存在该用户的表行中,以便稍后下载。我做了一切,但我收到了这个错误:
The property 'ApplicationUser.contract' is of an interface type ('IFormFile'). If it is a navigation property manually configure the relationship for this property by casting it to a mapped entity type
我不明白“将它投射到映射的实体类型”是什么意思,我错过了什么?这是我的方法:
首先,上传文件:
var path = Path.Combine(Directory.GetCurrentDirectory(), "Uploads",model.FileToUpload.GetFilename());
using (var stream = new FileStream(path, FileMode.Create))
{
await model.FileToUpload.CopyToAsync(stream);
}
然后,将其添加到用户的属性中
var user = new ApplicationUser { UserName = model.username, Email = model.Email, contract = model.FileToUpload };
应用程序用户在模型中有这个:public IFormFile contract {get; set;}
并且registerviewmodel具有:public IFormFile FileToUpload { get; set; }
任何帮助都会非常感激。
答案 0 :(得分:1)
您的错误消息来自实体框架。您可以在此处阅读有关此内容的完整详细信息:https://docs.microsoft.com/en-us/ef/core/modeling/relationships
简而言之,ApplicationUser
在实体框架的DbContext
内被指定为实体。 EF Core通常会尝试将实体类的每个属性映射到数据库中的值。 EF Core无法直接将IFormFile
映射到数据类型,以便在数据库中创建列(在您的情况下也不需要)。
所以,你的第一步就是告诉EF Core“不要担心这个属性”。这是通过在NotMapped
媒体资源上添加IFormFile
注释来完成的。下一步是将文件名保存到数据库中以供参考。我注意到您正在使用上传的文件名来执行此操作。为避免名称冲突,您可以使用Guid.NewGuid().ToString()
之类的内容生成唯一字符串(不要忘记添加扩展名)。要将此文件名保存到数据库中,您需要在ApplicationUser
类中创建字符串属性,仅保存文件名。文件本身不需要进入user
对象。
答案 1 :(得分:0)
为了补充Neville的答案,我建议您创建一个ApplicationUserViewModel
,这样您就可以将前端逻辑和输入/验证与您用于数据库的模型域分开,更具体地说,在ApplicationUserViewModel
您获取文件合约IFormFile
,并在之前的ApplicationUser
类中创建属性ID,如:
public class ApplicationUser : ...
{
//... other properties
[ForeignKey("Contracts")]
public string ContractId { get; set; }
}
并创建另一个域模型类,如Contracts
:
public class Contracts
{
public Guid Id { get; set; }
public byte[] FileBlob { get; set; }
public string FileExtension { get; set; }
}
所以在你的实际ApplicationUser
中你没有存储整个文件blob但是有一个对它的引用,这导致比每次实例ApplicationUser
时下载blob更高的性能