简体   繁体   English

拆分实体数据模型的属性上的数据注释[必需]属性

[英]Data Annotations [Required] attribute on property of split Entity Data Model

I'm using the Table Splitting feature of the Entity Framework to split my Entity Data Model as follows: 我正在使用实体框架的表拆分功能来拆分我的实体数据模型,如下所示:

+--------+    +--------------+
|  News  |    |  NewsImages  |
+--------+    +--------------+
| NewsID |    | NewsID       |
| Text   |    | Image        |
+--------+    +--------------+

Each News entity contains a navigation property called NewsImage to reference the corresponding image. 每个News实体都包含一个称为NewsImage的导航属性,以引用相应的图像。


I'm using DataAnnotations to validate my Model. 我正在使用DataAnnotations验证我的模型。 I put the [Required] attribute on the Text property of the News class: 我将[Required]属性放在News类的Text属性上:

[MetadataType(typeof(NewsValidation))]
public partial class News
{
    /* ... */
}

public class NewsValidation
{
    [Required]
    public string Text { get; set; }
}

Here is the server-side code I use to obtain the image data: 这是我用来获取图像数据的服务器端代码:

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

After calling the UpdateNewsImage(news) method, the entity news is populated correctly with the corresponding image data but the ModelState.IsValid property is still false ; 调用UpdateNewsImage(news)方法后,将使用相应的图像数据正确填充实体news ,但是ModelState.IsValid属性仍为false debugging ModelState.Values results in one error: "The NewsImage field is required." 调试ModelState.Values导致一个错误: “ NewsImage字段是必需的。” .


How can I put the [Required] attribute (or some other mechanism enforcing an image for each News entity) on the NewsImage property? 如何在NewsImage属性上放置[Required]属性(或其他为每个News实体强制图像的机制)?

Why not putting a [Required] attribute on NewsImage property inside your validation class? 为什么不在验证类内的NewsImage属性上放置[Required]属性? This will make it required that a News entity instance has a corresponding NewsImage entity instance as well. 这将要求News实体实例也具有相应的NewsImage实体实例。

When putting RequiredAttribute on reference (as in non-string) type properties it only checks that property is not null. 当将RequiredAttribute放在引用(如非字符串)类型属性时,它仅检查该属性不为null。 Let me back this up by the RequiredAttribute.IsValid() method: 让我通过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;
}

If you model state is invalid it means that your NewsImage is null. 如果建模状态无效,则意味着NewsImage为null。 Maybe you're missing something obvious here and some other property invalidates your model state. 也许您在这里缺少明显的东西,并且其他一些属性使模型状态无效。

Asp.net MVC file data binding ASP.NET MVC文件数据绑定

I get it. 我知道了。 It seems that you think that model state will be validated each time you do something to your model. 似乎您认为每次对模型进行操作时都会验证模型状态。 That is of course not the case. 当然不是这样。 Asp.net MVC automatically validates your action parameters for you before executing the action. 在执行操作之前,Asp.net MVC会自动为您验证操作参数。 So when your model state is invalid when you're in the body of your action method, it will stay that way no matter what you do to your model objects. 因此,当您处于动作方法的主体中时,如果模型状态无效,则无论您对模型​​对象做什么,它都会保持这种状态。 Unless of course you manually manipulate model state. 当然,除非您手动操作模型状态。 In your case when you add the image to your News still doesn't change model state (even though your object becomes valid). 在您的情况下,将图像添加到“ News中时,模型状态仍然不会更改(即使您的对象变为有效)。

As much as I understand it you have a problem with types. 据我了解,您对类型有疑问。 Asp.net MVC default model binder is able to automatically bind posted file streams to HttpPostedFileBase variables. Asp.net MVC默认模型绑定程序能够自动将发布的文件流绑定到HttpPostedFileBase变量。 Your NewsImage.Image property is of type byte[] hence it doesn't get auto-bound. 您的NewsImage.Image属性的类型为byte[]因此不会自动绑定。

The problem is that you're using data model entities in your web application as application/view model entities so you can't just change NewsImage.Image type because it's part of your EF data model. 问题在于您在Web应用程序中将数据模型实体用作应用程序/视图模型实体,因此您不能仅更改NewsImage.Image类型,因为它是EF数据模型的一部分。

To get this thing to work I suppose the best/easiest way would be to write a separate view model entity class (don't confuse it to EF data model) with correct property types and add it a public method that converts it to data model News entity. 为了使此功能正常工作,我认为最好/最简单的方法是编写一个具有正确属性类型的单独的视图模型实体类(不要将其与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[]
                }
            }
        }
    }
}

Your view model object will therefore be correctly model bound and validated as expected. 因此,您的视图模型对象将正确地绑定模型并按预期进行验证。 The good thing is that your code will get simplified due to this change as well. 好消息是,由于此更改,您的代码也将得到简化。 Use ToData() method when you need to get data entity instance from this view model object instance. 需要从该视图模型对象实例获取数据实体实例时,请使用ToData()方法。 You could of course provide the oposite as well, by providing a constructor that takes the data model entity object instance and populate view model's properties. 当然,您也可以通过提供一个构造函数来提供相反的构造函数,该构造函数采用数据模型实体对象实例并填充视图模型的属性。

If you use a separate database project where you keep your EF data model, I suggest you put your view model class strictly in the web application project (or any other application model project) because that's where it's used. 如果您使用单独的数据库项目来保存EF数据模型,则建议您将视图模型类严格放在Web应用程序项目(或任何其他应用程序模型项目)中,因为这是使用它的地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM