Подход к валидации в приложении CRC MVC3 с использованием WCF на основе EF4 в качестве бэкэнда - PullRequest
0 голосов
/ 26 октября 2011

Я разрабатываю простое приложение MVC3 CRUD - простые контроллеры / представления, которые используют службу WCF для доступа к данным CRUD.

WCF использует EF4.1 с DbContext и простые методы в стиле CRUD: ListEntities, GetEntity(ID), AddEntity (entity), DeleteEntity (ID)

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

Но в моем приложении я не использую этот подход и сталкиваюсь с двумяпроблемы:

  1. Мои объекты в WCF генерируются из EDMX, который, в свою очередь, также генерируется из базы данных.Поэтому я не могу добавить к ним какие-либо атрибуты аннотации проверки данных, потому что они исчезнут, как только сущности будут восстановлены из EDMX.Есть ли какое-либо решение для этого?

  2. Так как мой клиент (приложение MVC) не разделяет классы контракта данных с WCF (для четкого разделения), а вместо этого генерируется ссылка на службу формы,даже если я найду способ добавить атрибуты аннотации данных в классы контракта данных на стороне сервера, будут ли они распознаваться и создаваться заново при создании прокси-класса контракта данных на стороне клиента?
    Итак, как я мог заставить приложение MVC использоватьпроверка на стороне клиента и сообщение об ошибке для ошибок проверки при привязке к сущностям, предоставляемым службой WCF в качестве контрактов данных?

Одна из идей, которые у меня есть, на стороне клиента - создавать производные классы для всехсущности, предоставляемые в качестве контрактов данных, и применяют к ним атрибуты аннотаций к требуемым свойствам.Но это не выглядит хорошим решением для меня, потому что с помощью этого я создаю логическую «связь» между клиентом пользовательского интерфейса и уровнем сервиса / данных WCF (заставляя пользовательский интерфейс знать о данных больше, чем следует - помещая логику BLв клиенте).

Может кто-нибудь дать мне несколько советов о том, как справиться с этими ситуациями?

Спасибо

Ответы [ 3 ]

2 голосов
/ 26 октября 2011

1: Да, вы можете добавить проверку, используя System.ComponentModel.DataAnnotations.MetaDataType .

Я ответил на этот вопрос в Обновления частичной модели MVC

2a: То, что вы можете сделать, - это создать отдельную сборку библиотеки классов, которая содержит все интерфейсы (с дополнительными MetaDataTypes или без нее) и использовать ее как в службе WCF, так и в приложении MVC.После добавления ссылки в приложение MVC при добавлении ссылки на службу WCF вы можете сопоставить DataContacts службы WCF непосредственно с интерфейсами в сборке.Одно предостережение заключается в том, что и служба WCF, и приложение MVC зависят от сборки (некоторые могут посчитать, что это тесно связано), но это должно быть нормально, потому что вы только тесно связаны на уровне интерфейса, и независимо от того, хотите ли вы разрешить VSвоссоздать его собственные интерфейсы / классы или повторно использовать то, что вы уже создали в сборке, на мой взгляд, все сводится к тому же.

2b: Если вы решите не использовать библиотеку классов, я вполне уверен, чтосправочные классы служб являются частичными, и вы можете просто создать другой файл .cs с частичными классами и добавить интерфейсы, как я описал в части 1, к частичным классам.

Обновление

В настоящее время я использую Entity Framework для доступа к моей базе данных.Entity Framework, как и WCF References, классы автоматически генерируемых классов будут выглядеть примерно так:

[EdmEntityTypeAttribute(NamespaceName="MyNameSpace", Name="Info ")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Info : EntityObject
{
    public static Info CreateInfo (global::System.Int32 id)
    {
        Info info= new Info ();
        info.Id = id;
        return info;
    }

    public string Name { get; set; }
    public string FavoriteColor { get; set; }       

    // etc etc

}

В отдельном файле с тем же пространством имен, что и у предыдущего частичного класса, я создал:

[SomeAttribute1]
[AnotherAttribute2]
public partial class Info: IInfo
{
}

Так что теперь мой автоматически сгенерированный класс основан не только на интерфейсе, который я создал IInfo, поэтому фактические методы не предоставляются (потому что мой datatier в MVC возвращает интерфейсы), но он также имеет атрибуты (для аннотаций данных)или что-то в этом роде.

Я хотел бы предложить вместо размещения аннотаций данных непосредственно в ссылочном классе службы WCF использовать метаданные MetedataType.Это позволяет отделить реальный объект данных от проверок аннотаций данных.Особенно полезно, если вы хотите использовать один и тот же класс данных с разными проверками, основанными на чем угодно (возможно, администраторам не нужно иметь правильный любимый цвет).

Например:

public interface NormalUser
{
  [Required]
  string Name { get; set; }
  [Required]
  string FavoriteColor { get; set; }
}

public interface AdminUser
{
  [Required]
  string Name { get; set; }
  string FavoriteColor { get; set; }
}

[MetadataType(typeof(INormalUser))
public class NormalUserInfo : Info { }

[MetadataType(typeof(IAdminUser))
public class AdminUserInfo : Info { }

В этом примере у нас есть два разных класса NormaUserInfo и AdminUserInfo, которые имеют разные проверки.Каждый из них унаследован от Info, поэтому он является допустимой моделью, которую можно передать в службу WCF.

1 голос
/ 26 октября 2011

Что касается проверки, вы можете использовать: http://fluentvalidation.codeplex.com/

1 голос
/ 26 октября 2011

Не в своем уме, я не могу это сейчас проверить ...

Допустим, ваш автоматически сгенерированный код выглядит так:

public partial class Employee
{
//some code here
}

Вы можете добавить новый класс Employee, также частичный, и этот класс не будет создан автоматически

[you can annotate here]
public partial class Employee
{
//somecode here
}

попробуйте

...