Mar*_*ulz 1 c# asp.net-mvc entity-framework data-annotations
我正在使用Entity Framework 的Table Splitting功能来拆分我的实体数据模型,如下所示:
+--------+ +--------------+
| News | | NewsImages |
+--------+ +--------------+
| NewsID | | NewsID |
| Text | | Image |
+--------+ +--------------+
Run Code Online (Sandbox Code Playgroud)
每个News实体都包含一个名为NewsImage引用相应图像的导航属性.
我正在使用DataAnnotations来验证我的模型.我把[Required]属性上Text的财产News类:
[MetadataType(typeof(NewsValidation))]
public partial class News
{
/* ... */
}
public class NewsValidation
{
[Required]
public string Text { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是我用来获取图像数据的服务器端代码:
[HttpPost]
public ActionResult Create(News news)
{
if (ModelState.IsValid)
{
UpdateNewsImage(news);
_newsRepository.Add(news);
_newsRepository.SaveChanges();
return RedirectToAction("Index");
}
}
private void UpdateNewsImage(News news)
{
byte[] newsImage = GetNewsImage();
news.NewsImage = new NewsImage { Image = newsImage };
}
private byte[] GetNewsImage()
{
foreach (string upload in Request.Files)
{
HttpPostedFileBase uploadedFile = Request.Files[upload];
if (!uploadedFile.HasFile())
{
break;
}
Stream fileStream = uploadedFile.InputStream;
int fileLength = uploadedFile.ContentLength;
byte[] fileData = new byte[fileLength];
fileStream.Read(fileData, 0, fileLength);
return fileData;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
调用后UpdateNewsImage(news)的方法,所述实体news被正确填充与相应的图像数据,但ModelState.IsValid属性仍然false; 调试ModelState.Values导致一个错误:"NewsImage字段是必需的." .
如何在[Required]属性上放置属性(或为每个News实体强制执行图像的其他机制)NewsImage?
为什么不在验证类中放置[Required]属性NewsImage?这将使得News实体实例也需要具有相应的NewsImage实体实例.
将RequiredAttribute放在引用(如在非字符串中)类型属性时,它仅检查该属性是否为null.让我通过这个RequiredAttribute.IsValid()方法来支持这个:
public override bool IsValid(object value)
{
if (value == null)
{
return false;
}
string str = value as string;
if (str != null)
{
return (str.Trim().Length != 0);
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
如果模型状态无效,则表示您的状态NewsImage为null.也许你错过了一些明显的东西,其他一些属性使你的模型状态无效.
我知道了.您似乎认为每次对模型执行某些操作时都会验证模型状态.当然不是这样.在执行操作之前,Asp.net MVC会自动为您验证操作参数.因此,当您处于动作方法体内时,模型状态无效时,无论您对模型对象执行何种操作,它都将保持这种状态.除非您手动操作模型状态.在您的情况下,将图像添加到News静止不会更改模型状态(即使您的对象变得有效).
据我所知,你有类型的问题.Asp.net MVC默认模型绑定器能够自动将发布的文件流绑定到HttpPostedFileBase变量.您的NewsImage.Image属性属于类型,byte[]因此不会自动绑定.
问题是您在Web应用程序中使用数据模型实体作为应用程序/视图模型实体,因此您不能只更改NewsImage.Image类型,因为它是EF数据模型的一部分.
为了让这个东西起作用,我认为最好/最简单的方法是用正确的属性类型编写一个单独的视图模型实体类(不要将它与EF数据模型混淆),并添加一个将其转换为数据模型的公共方法News实体.
namespace WebProject.ViewModels
{
public class News
{
public int Id { get; set; } // not used when creating new entries but used with editing/deleting hens not being required
[Required]
public string Text { get; set; }
[Required]
public HttpPostedFileBase Image { get; set; }
public Data.News ToData()
{
return new Data.News {
Id = this.Id,
Text = this.Text,
NewsImage = new Data.NewsImage {
Id = this.Id,
Image = // convert to byte[]
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,您的视图模型对象将按预期正确地进行模型绑定和验证.好的是,由于这种变化,您的代码也会得到简化.ToData()需要从此视图模型对象实例获取数据实体实例时使用方法.当然,您也可以通过提供构造函数来提供对话框,该构造函数接受数据模型实体对象实例并填充视图模型的属性.
如果您使用单独的数据库项目来保存EF数据模型,我建议您将视图模型类严格地放在Web应用程序项目(或任何其他应用程序模型项目)中,因为这是它的使用位置.