Asp.net mvc 基于EF4的WCF作为后端的MVC3 CRUD应用程序验证方法

Asp.net mvc 基于EF4的WCF作为后端的MVC3 CRUD应用程序验证方法,asp.net-mvc,wcf,asp.net-mvc-3,validation,wcf-client,Asp.net Mvc,Wcf,Asp.net Mvc 3,Validation,Wcf Client,我开发了一个简单的MVC3 CRUD应用程序——简单控制器/视图,它使用WCF服务访问CRUD数据 WCF将EF4.1与DbContext一起使用,并使用简单的CRUD样式方法:Listenties、GetEntity(ID)、AddEntity(entity)、DeleteEntity(ID) 如果我直接使用EF、code first开发MVC应用程序,我可以使用验证属性注释实体类中的属性,当我尝试保存验证错误时,MVC应用程序将自动识别验证错误并在UI中报告它们(例如,未设置必填字段) 但在

我开发了一个简单的MVC3 CRUD应用程序——简单控制器/视图,它使用WCF服务访问CRUD数据

WCF将EF4.1与DbContext一起使用,并使用简单的CRUD样式方法:Listenties、GetEntity(ID)、AddEntity(entity)、DeleteEntity(ID)

如果我直接使用EF、code first开发MVC应用程序,我可以使用验证属性注释实体类中的属性,当我尝试保存验证错误时,MVC应用程序将自动识别验证错误并在UI中报告它们(例如,未设置必填字段)

但在我的应用程序中,我没有使用这种方法,我面临两个问题:

  • WCF中的我的实体是从EDMX生成的,而EDMX又是从数据库生成的。因此,我实际上无法向它们添加任何数据验证注释属性,因为一旦从EDMX重新生成实体,它们就会消失。有什么解决办法吗

  • 由于我的客户端(MVC应用程序)不与WCF共享数据协定类(为了明确区分),而是从服务引用生成,即使我找到了向服务器端数据协定类添加数据注释属性的方法,在客户端创建数据协定代理类时,它们是否会被识别并重新创建?
    那么,当绑定到WCF服务作为数据契约公开的实体时,如何使MVC应用程序使用客户端验证和错误消息报告验证失败呢

  • 我的一个想法是,在客户端,为作为数据契约公开的所有实体创建派生类,并将注释属性应用到它们所需的属性。但对我来说,这并不是一个好的解决方案,因为我用它在UI客户机和WCF服务/数据层之间创建了一个逻辑“耦合”(通过在客户机中放置BL逻辑,迫使UI对数据的了解超过它应该知道的)

    有谁能给我一些关于如何处理这种情况的建议吗


    谢谢

    1:是的,您可以使用添加验证

    我当时回答了这个问题

    2a:您可以创建一个单独的类库程序集,其中包含所有接口(带或不带附加元数据类型),并在WCF服务和MVC应用程序上使用它。将引用添加到MVC应用程序后,在添加WCF服务引用时,可以将WCF服务DataContacts直接匹配到程序集中的接口。一个警告是,WCF服务和MVC应用程序都依赖于程序集(有些人可能认为这是紧密耦合的),但这应该是可以的,因为您只在接口级别上紧密耦合,无论您是否选择允许VS重新创建它自己的接口/类或重用您在程序集中已经创建的接口/类,在我看来都归结为同一件事

    2b:如果您决定不使用类库,我很确定服务引用类是部分的,您可以简单地创建另一个带有部分类的.cs文件,并将我在第1部分中描述的接口添加到部分类中

    更新

    我目前正在使用实体框架访问我的数据库。实体框架,与WCF引用一样,类是自动生成的类,看起来类似于:

    [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
    ,因此不会公开实际的方法(因为我在MVC中的datatier返回接口),而且它还具有属性(用于数据注释或其他)

    我建议使用MetedataType DataAnnotations,而不是将数据注释直接放在WCF服务引用类上。这允许您将实际数据对象与数据注释和验证分离。如果您希望使用相同的数据类并基于任何原因进行不同的验证(可能管理员不必使用有效的收藏夹颜色),那么这将非常有用

    例如:

    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 { }
    

    在本例中,我们有两个不同的类
    normaluserinfo
    AdminUserInfo
    ,它们都具有不同的验证。它们中的每一个都继承自
    Info
    ,因此它们都是可以传递到WCF服务中的有效模型。

    1:是的,您可以使用添加验证

    我当时回答了这个问题

    2a:您可以创建一个单独的类库程序集,其中包含所有接口(带或不带附加元数据类型),并在WCF服务和MVC应用程序上使用它。将引用添加到MVC应用程序后,在添加WCF服务引用时,可以将WCF服务DataContacts直接匹配到程序集中的接口。一个警告是,WCF服务和MVC应用程序都依赖于程序集(有些人可能认为这是紧密耦合的),但这应该是可以的,因为您只在接口级别上紧密耦合,无论您是否选择允许VS重新创建它自己的接口/类或重用您在程序集中已经创建的接口/类,在我看来都归结为同一件事

    2b:如果您决定不使用类库,我很确定服务引用类是部分的,您可以简单地创建另一个带有部分类的.cs文件,并将我在第1部分中描述的接口添加到部分类中

    更新

    我目前正在使用实体框架访问我的数据库。实体框架,与WCF引用一样,类是自动生成的类,看起来类似于:

    [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
    {
    }
    
    所以现在我的自动生成类不仅仅基于一个Inter