以基于 EF4 的 WCF 作为后端的 MVC3 CRUD 应用程序的验证方法

发布于 2024-12-11 15:44:06 字数 824 浏览 0 评论 0原文

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

WCF 将 EF4.1 与 DbContext 一起使用,以及简单的 CRUD 样式方法:ListEntities、GetEntity(ID)、AddEntity(实体)、DeleteEntity(ID)

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

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

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

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

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

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

谢谢

I develop a simple MVC3 CRUD application - simple controllers / views, which uses WCF service for CRUD data access.

The WCF uses EF4.1 with DbContext, and simple CRUD-style methods: ListEntities, GetEntity(ID), AddEntity (entity), DeleteEntity(ID)

If I develop the MVC application directly with EF, code first, I can annotate properties in the entity classes with validation attributes, and the MVC application will automatically recognize validation errors and report them in the UI when I try to save and a validation error occurs (e.g. a required field is not set).

But in my application I don't use this approach and I face two problems:

  1. My entities in the WCF are generated from the EDMX, which in turn was also generated from the database. So I cannot actually add to them any data validation annotation attributes, because they'll vanish as soon as the entities will be regenerated from the EDMX. Is there any solution to this?

  2. Since my client (MVC app) does not share the data contract classes with WCF (for clear separation), but instead it is generated form service reference, even if I find a way to add data annotation attributes to server-side data contract classes, will they be recognized and recreated when the data contract proxy class is created on client side?
    So how could I made the MVC application to use client side validation and error message reporting for validation failures when binding to entities exposed by WCF service as data contracts?

One idea I have is, on client side, to create derived classes for all entities exposed as data contracts, and apply annotation attributes to them to desired properties. But this doesn't looks like a good solution to me, because with this I create a logic "coupling" between UI client and the WCF service / data layer (forcing UI to know about data more than it should do - by putting BL logic in client).

Can anyone give me some suggestions on how to handle those this situation?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌路黄昏 2024-12-18 15:44:06

1:是的,您可以使用 System.ComponentModel 添加验证.DataAnnotations.MetaDataType

我在MVC部分模型更新回答了这个问题

2a:你可以做的是创建一个单独的类库程序集,其中包含所有接口(带或不带附加元数据类型),并在 WCF 服务和 MVC 应用程序上使用它。将引用添加到 MVC 应用程序后,在添加 WCF 服务引用时,您可以将 WCF 服务数据联系人直接与程序集中的接口匹配。需要注意的是,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 中的数据层返回接口),但它也具有属性(用于数据注释或其他内容)。

我建议不要将数据注释直接放在 WCF 服务引用类上,而是使用 MetedataType DataAnnotations。这允许您将实际数据对象与数据注释验证分开。如果您想根据任何情况使用具有不同验证的相同数据类(也许管理员不必拥有有效的最喜欢的颜色),则特别有用。

例如:

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

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

1: Yes you can add validation using the System.ComponentModel.DataAnnotations.MetaDataType.

I answered this question at MVC Partial Model Updates

2a: What you can do is create a seperate Class Library Assembly that contains all the interfaces (with or without additional MetaDataTypes) and use that on both the WCF service and the MVC application. After you add the reference to your MVC application, when adding the WCF Service reference, you can match the WCF Service DataContacts directly to the interfaces in the Assembly. One Caveat is that both the WCF service and MVC application are dependant on the Assembly (some might consider this tightly coupled) but this should be ok because you are only tightly coupling at the interface level, and whether or not you choose to allow VS to recreate it's own interfaces/classes or reuse what you already created in the Assembly it boils down to the same thing in my opinion.

2b: If you decide not to use a Class Library, I'm pretty sure that the service reference classes are partial, and you can simply create another .cs file with partial classes and add the interfaces as I described in part 1 to the partial classes.

Update

I am currently using Entity Framework to access my database. Entity Framework, like WCF References, classes are Auto-Generated classes will look something similar to:

[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

}

In a separate file with the same namespace as the previous partial class, I have created:

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

So now my auto-generated class is not only based on an Interface I created IInfo so the actual methods are not exposed (because my datatier in MVC returns interfaces), but it also has Attributes (for Data Annotations or whatever).

What I would suggest is instead of putting your data annotations directly on your WCF Service reference class is to use the MetedataType DataAnnotations. This allows you to separate the actual data object with the data annotations validations. Especially helpful if you want to use the same data class with different validations based on whatever (maybe administrators don't have to have a valid favorite color).

For example:

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

In this example we have two different classes NormaUserInfo and AdminUserInfo which both have different validations. Each of them have inherited from Info so they are valid models that can be passed into the WCF Service.

皇甫轩 2024-12-18 15:44:06

我疯了,因为我现在无法测试它......

假设您的自动生成的代码是这样的:

public partial class Employee
{
//some code here
}

您可以添加一个新的 Employee 类,也是部分的,并且这个不会自动生成

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

尝试一下

Out of my mind, as I can't test it right now...

Let's say your autogenerated code is like this:

public partial class Employee
{
//some code here
}

You can add a new Employee class, also partial, and this one won't be autogenerated

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

try it

陪我终i 2024-12-18 15:44:06

至于验证,您可以使用: http://fluidation.codeplex.com/

As for the validation, you could use: http://fluentvalidation.codeplex.com/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文