Атрибут Аннотации данных [Обязательный] для свойства разделяемой модели данных Entity - PullRequest
1 голос
/ 31 января 2011

Я использую функцию Table Splitting Entity Framework, чтобы разделить мою модель данных Entity следующим образом:

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

Каждый объект News содержит свойство навигации, называемое NewsImage для ссылки на соответствующее изображение.


Я использую DataAnnotations для проверки моей модели.Я поместил атрибут [Required] в свойство Text класса News:

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

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

Вот код на стороне сервера, который я использую для получения данных изображения:

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

После вызова метода UpdateNewsImage(news) объект news равен , правильно заполненный соответствующими данными изображения, но свойство ModelState.IsValid по-прежнему false;отладка ModelState.Values приводит к одной ошибке: «Поле NewsImage является обязательным.» .


Как поставить атрибут [Required] (или какой-либо другой механизм, обеспечивающий принудительное использование изображениядля каждой News сущности) в свойстве NewsImage?

1 Ответ

6 голосов
/ 31 января 2011

Почему бы не поместить атрибут [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;
}

Если ваше модельное состояние недопустимо, это означает, что ваш NewsImage равен нулю. Возможно, вы упускаете что-то очевидное здесь, и какое-то другое свойство делает недействительным ваше состояние модели.

Привязка данных файла MVC Asp.net

Я понял. Кажется, что вы думаете, что состояние модели будет проверяться каждый раз, когда вы что-то делаете с вашей моделью. Это, конечно, не тот случай. Asp.net MVC автоматически проверяет параметры вашего действия перед выполнением действия. Поэтому, когда ваше состояние модели недопустимо, когда вы находитесь в теле метода действия, оно останется таким, независимо от того, что вы делаете с объектами модели. Если, конечно, вы вручную не управляете состоянием модели. В вашем случае, когда вы добавляете изображение в News, оно по-прежнему не меняет состояние модели (даже если ваш объект становится действительным).

Насколько я понимаю, у вас проблема с типами. Механизм связывания моделей по умолчанию для Asp.net MVC может автоматически связывать потоки опубликованных файлов с HttpPostedFileBase переменными. Ваше свойство NewsImage.Image имеет тип byte[], поэтому оно не привязывается автоматически.

Проблема в том, что вы используете сущности модели данных в своем веб-приложении в качестве сущностей модели приложения / представления, поэтому вы не можете просто изменить тип 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[]
                }
            }
        }
    }
}

Следовательно, ваш объект модели представления будет правильно привязан к модели и проверен, как и ожидалось. Хорошо, что ваш код также будет упрощен благодаря этому изменению. Используйте метод ToData(), когда вам нужно получить экземпляр объекта данных из этого экземпляра объекта модели представления. Конечно, вы также можете указать и опозицию, предоставив конструктор, который принимает экземпляр объекта сущности модели данных и заполняет свойства модели представления.

Если вы используете отдельный проект базы данных, в котором хранится ваша модель данных EF, я предлагаю вам строго поместить класс модели представления в проект веб-приложения (или любой другой проект модели приложения), потому что именно там он используется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...