Архитектура MVC - повторное использование одной и той же модели представления для чтения и редактирования - PullRequest
5 голосов
/ 24 января 2012

Скажем, у нас есть следующий (слишком простой) сценарий:

У нас есть экран для просмотра сведений о человеке и экран для редактирования сведений о человеке.

Сведения о человеке на экране имеют следующие поля (только для отображения):

Имя Фамилия Bio

На экране редактирования сведений о человеке отображаются следующие поля (в элементах управления вводом):

ID (скрыто) Имя Фамилия Bio

Скажем, наша модель отображения выглядит следующим образом:

    public class DisplayPersonViewModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Bio { get; set; }
    }

И наша правка редактирования выглядит так:

public class EditPersonViewModel
{
    [Required]
    public int ID { get; set; }

    [Required]
    [StringLength(20)]
    public string FirstName { get; set; }

    [Required]
    [StringLength(20)]
    public string LastName { get; set; }

    [Required]
    public string Bio { get; set; }
}

Не так много различий между двумя, а? Модель редактирования имеет одно дополнительное поле (ID) и некоторые атрибуты в свойствах. Теперь, если бы мы объединили 2 как это:

    public class DisplayPersonViewModel
    {
        [Required]
        [StringLength(20)]
        public string FirstName { get; set; }

        [Required]
        [StringLength(20)]
        public string LastName { get; set; }

        [Required]
        public string Bio { get; set; }
    }

    public class EditPersonViewModel : DisplayPersonViewModel
    {
        [Required]
        public int ID { get; set; }
    }

Это, безусловно, более СУХОЙ, поскольку у нас нет дублирующих полей для обслуживания, но теперь у нас есть посторонняя информация (атрибуты) в нашей модели отображения. Я все больше склоняюсь ко второму подходу, потому что на некоторых наших экранах более 25 полей! (... и это вне моего контроля, поэтому, пожалуйста, не говорите об этом :) ...) Однако я просто хочу услышать мнения, чтобы лучше понять, что может быть "наилучшей практикой".

Ответы [ 2 ]

4 голосов
/ 24 января 2012

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

К сожалению, лично я не могу жить с этим чувством в животе, и поэтому я использую FluentValidation.NET , чтобы определить мои правила проверки вместо аннотаций данных. Это позволяет мне иметь эти правила отдельно от моих моделей представлений, и тогда я не беспокоюсь о загрязнении так называемой модели отображаемых представлений правилами валидации. Таким образом, я бы определил так же, как вы, 2 модели просмотра, и EditPersonViewModel будет производным от DisplayPersonViewModel, а затем определите мои EditPersonViewModelValidator для EditPersonViewModel в отдельном классе.

Да и примечание: украшать ненулевой тип атрибутом [Required] необязательно. Все необнуляемые типы обязательны по своей самой основной природе. Так что вместо:

[Required]
public int ID { get; set; }

Вы должны иметь только:

public int ID { get; set; }
1 голос
/ 24 января 2012

Другой вариант - использовать атрибут MetadataType .

public class PersonModel
{
  public int ID { get; set; }   
  public string FirstName { get; set; }  
  public string LastName { get; set; }   
  public string Bio { get; set; }   
}

[MetadataType(typeof(IDisplayPersonViewModel))]
public class DisplayPersonViewModel : PersonModel

[MetadataType(typeof(IEditPersonViewModel))]
public class EditPersonViewModel : PersonModel

public interface IDisplayPersonViewModel
{
  [ScaffoldColumn(false)]
  public int ID { get; set; }   
}

public interface IEditPersonViewModel
{
  [Required]                
  [StringLength(20)]                
  public string FirstName { get; set; }                

  [Required]                
  [StringLength(20)]                
  public string LastName { get; set; }                

  [Required]                
  public string Bio { get; set; }                

  [Required]                
  public int ID { get; set; }             
} 

Ваша необработанная модель Person не имеет атрибутов.Ваши модели Display и Edit имеют только те атрибуты, которые вам действительно нужны для просмотра.

...