5

ASP.NET | MVC 4 | C# | WCF

我使用 WCF Web 服务作为从表示层 (MVC) 到数据层 (Entity) 的中介。为了简化将数据模型数据从 MVC 移动到 Web 服务,我想我会在 WCF 中使用代理类,这样就会有一个集中的类。不幸的是,这导致模型内属性上的 MVC 装饰丢失。有没有一种好方法可以创建一个集中的类以与 MVC 视图的模型一起使用,也可以作为 WCF 服务的传输方法?

自动映射是一种选择,但我相信这需要两个相同的类。一个在 MVC 端,一个在 WCF 端。如果类中的属性发生更改,这仍然需要我在双方都进行更改。

任何其他建议将不胜感激。谢谢!

编辑:: 示例

这是包含记录表的页面的模型

public class ReconcileModel
{
    #region PROPERTIES

    public List<ReconcileItem> ReconcileItems { get; set;}

    #endregion

    #region CONSTRUCTORS

    public ReconcileModel()
    {
        ReconcileItems = new List<ReconcileItem>();
    }

    #endregion
}

这是一个代表该表中每条记录的类。

public class ReconcileItem
{
    #region PROPERTIES

    public int ID { get; set; }
    public string Description { get; set; }
    public string LastLocation { get; set; }
    public string LastRead { get; set; }
    public string IntendenLocation { get; set; }
    public string PickId { get; set; }
    public string OEM { get; set; }
    public string LotNumber { get; set; }
    public string SerialNumber { get; set; }
    public DateTime ExpirationDate { get; set; }
    public string ReconcileReason { get; set; }
    public string RemoveReason { get; set; }


    #endregion

    #region CONSTRUCTORS

    public ReconcileItem()
    {
    }

    #endregion
}

上述类的 WCF 合同表示将是

[DataContract]
public class ReconcileItem
{
    [DataMemeber]
    public int ID { get; set; }
    [DataMember]
    public string Description { get; set; }
    [DataMember]
    public string LastLocation { get; set; }
    [DataMember]
    public string LastRead { get; set; }
    [DataMember]
    public string IntendenLocation { get; set; }
    [DataMemeber]
    public string PickId { get; set; }
    [DataMember]
    public string OEM { get; set; }
    [DataMember]
    public string LotNumber { get; set; }
    [DataMember]
    public string SerialNumber { get; set; }
    [DataMember]
    public DateTime ExpirationDate { get; set; }
    [DataMember]
    public string ReconcileReason { get; set; }
    [DataMember]
    public string RemoveReason { get; set; }
}

如果我想更新这条记录,该类被发送到 WCF 服务,映射到适当的实体框架类,并保存到数据库中。为了简化传输,我想我只是将这个类放在 WCF 项目中,并在 MVC 项目中引用它。然后我可以在 WCF 和 MVC 之间来回传递这个类。此外,如果我在 WCF 中更新了类,那么它将反映在 MVC 中。这就是中心化的意思。

4

3 回答 3

2

您仍然可以使用您的实体,但创建视图模型并将您的数据注释放在这些上。有很多关于在项目中将验证放在哪里的讨论。一般来说,它几乎总是需要发生在 UI 上,然后通常也发生在其他地方。我会避免尝试集中它,因为这永远不会奏效(一种尺寸很少适合所有人)。

关于在您的解决方案中嵌入 WCF 层的主题,除非有很好的理由,否则我会不惜一切代价避免这样做。我已经多次看到这种事情出错了。它带来了很多负面影响。在我处理的两个商业案例中,你最终会遇到太多的端点和太多的闲聊。它削弱了将业务逻辑放入您的实体并通过网络使用这些方法的能力,使维护成为一场噩梦,并且没有足够的硬件和精心的设计,如果托管在单个服务器上,您最终可能不得不使用命名管道来获得所需的速度,这抵消了使用 WCF 获得的任何分布式优势。

您最好将繁重的处理任务外部化为可以在其他地方托管并通过更小、更简洁的界面进行通信的组件。实际上,除了图像处理、数学和科学应用之外,不会出现繁重的数据处理。

于 2013-09-10T21:58:16.507 回答
2

我们按照您在我当前雇主的帖子中描述的方式使用 WCF。我们最终得到了用于 WCF 和 MVC 的 DTO 类,以便与 MVC 应用程序中的 ViewModels 进行通信,以便在 UI 中进行模型绑定和验证。

我同意拥有几乎相互重复的类并在它们之间进行映射是一种痛苦,而且在某种程度上似乎是错误的。从我过去读到的内容来看,我们所做的,以及你可能被迫做的,是最佳实践。

上面关于仅由 WCF 完成繁重处理的 Adrian 建议也很有意义。在开始我目前的工作之前,我就是这样做的。大部分业务逻辑被放置在 MVC 应用程序直接引用的业务层组件中。对于少数可能长时间运行的进程,我创建了单独托管的 WCF 服务,MVC 应用程序与之通信。

最后,您可以使用 Web API 与 WCF 吗?Web API 是轻量级的,并且使用 HTTP,没有 WCF 绑定等带来的所有开销。此外,使用 Web API,您可以使用 MVC 应用程序正在使用的相同类,甚至可以利用 Web API 中的模型验证。这是我一直在努力并且变得越来越普遍的事情。

希望有帮助!

于 2013-09-10T23:52:27.953 回答
2

就像 Adrian 一样,我质疑您是否真的需要在 DB 和 MVC 服务之间使用 WCF 服务。对于与数据库对话的客户端应用程序(Win Forms、WPF)来说,这种情况更有可能发生。我目前正在开发一个 Win Forms 项目,我们使用 WCF 作为中间层,我们执行以下操作:

  • 我们有一个在客户端和 WCF / BL 之间共享的程序集(称为“合同”)。
  • 此“合同”程序集包含所有通过线路由 WCF 发送和发送到 WCF 的 DTO。
  • 我们通过在服务引用设置中设置“指定引用程序集中的重用类型”,将 WCF 客户端代理配置为使用合同程序集(而不是让 WCF 重新生成所有 DTO)。
  • 我们用 DataAnnotations 属性(和其他元数据)装饰这些 DTO。
  • 我们不会使用 WCF 属性来装饰那些 DTO。WCF 不需要它们来序列化 DTO。它们是可选的。如果可以的话,把它们排除在外。它只会使您的代码混乱。
  • 由于客户端使用相同的程序集,我们可以在客户端上使用 DataAnnotations。
  • 我们也在服务器上进行验证。
  • 我们使用AutoMapper来完成从实体到 DTO 的大部分样板映射(但绝不会反过来)。
  • 坦率地说,您甚至不让 WCF 序列化我们的 DTO,而是使用JSON.NET,而 WCF 只发送和接收(纯文本)JSON,因为 JSON.NET 在序列化和反序列化数据方面更加灵活结构。例如,我们使用 JSON.NET 来(反)序列化不可变对象结构。用 WCF 试试。那将惨败。

最重要的是,我们这样做:

  • 使用 View Model 类添加客户端功能。
  • 在合同程序集中添加自定义 DataAnnotation 验证,以允许验证在客户端和服务器上运行。
  • 添加一个IValidator<T>抽象(某种形式)以允许特定于服务器或客户端的验证(通过将实现放置在您的业务层或客户端应用程序中)。
  • 使用异常将服务器特定的验证错误传输回客户端。
于 2013-09-11T08:28:48.397 回答