ASP.NET MVC - 模型的WCF类

时间:2022-08-24 22:12:50

ASP.NET | MVC 4 | C# | WCF

ASP.NET | MVC 4 | C#| WCF

I am using WCF web services as an intermediary from the presentation layer (MVC) to the data layer (Entity). To simplify moving data model data from MVC to the web service I thought I would use proxy classes in WCF, so that there would be one centralized class. Unfortunately, this caused the loss of MVC decorations on properties within the model. Is there a good way to create a centralized class for use with a model for the MVC view, and also as a transport method to the WCF service?

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

Automapping came to mind as an option, but I believe that would require two identical classes. One on the MVC side and one on the WCF side. Which would still require me to make a change on both sides if a property changed in a class.

作为一种选择,我想到了自动化,但我认为这需要两个相同的类。一个在MVC侧,一个在WCF侧。如果某个类中的属性发生变化,那么仍需要我对双方进行更改。

Any other suggestions would be appreciated. Thanks!

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

EDIT:: Example

Here is model for a page that contains a table of records

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

public class ReconcileModel
{
    #region PROPERTIES

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

    #endregion

    #region CONSTRUCTORS

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

    #endregion
}

Here is a class to represent each record in that table.

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

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
}

The WCF contract representation of the class above would be

上面的类的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; }
}

If I want to update this record, the class is sent to the WCF service, mapped to appropriate entity framework classes, and saved to the database. To simplify the transfer I thought I would just put this class in the WCF project and reference it in the MVC project. Then I could pass the class back in forth between WCF and MVC. Also, if I updated the class in WCF then it would be reflected in MVC. That's what is meant by centralized.

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

3 个解决方案

#1


2  

Just like Adrian, I question whether you actually need a WCF service between your DB and an MVC service. This is a much more likely scenario for a client application (Win Forms, WPF) that talks to a database. I'm currently working on a Win Forms project where we use WCF as intermediate layer and we do the following:

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

  • We have an assembly (called 'contract') that is shared between the client and the WCF / BL.
  • 我们有一个在客户端和WCF / BL之间共享的程序集(称为“契约”)。

  • This 'contract' assembly contains all DTOs that are sent over the wire by and to WCF.
  • 该“合同”程序集包含由WCF通过线路发送的所有DTO。

  • We configured the WCF client proxy to use the contract assembly (instead of letting WCF regenerate all DTOs) by setting the 'Reuse types in specified reference assemblies' in the Service Reference Settings.
  • 我们通过在“服务引用设置”中设置“指定引用程序集中的重用类型”,将WCF客户端代理配置为使用合同程序集(而不是让WCF重新生成所有DTO)。

  • We decorate those DTOs with DataAnnotations attributes (and other metadata).
  • 我们使用DataAnnotations属性(和其他元数据)来装饰这些DTO。

  • We don't decorate those DTOs with WCF attributes. WCF doesn't need them to serialize DTOs. They are optional. Leave them out if you can. It just clutters your code.
  • 我们不会使用WCF属性来装饰这些DTO。 WCF不需要它们来序列化DTO。它们是可选的。如果可以,请将它们留下。它只会使你的代码变得混乱。

  • Since the client uses the same assembly we can use DataAnnotations on the client.
  • 由于客户端使用相同的程序集,因此我们可以在客户端上使用DataAnnotations。

  • We validate on the server as well.
  • 我们也在服务器上验证。

  • We use AutoMapper to do most of the boilerplate mapping from entities to DTOs (but never the other way around).
  • 我们使用AutoMapper来完成从实体到DTO的大部分样板映射(但从来没有相反)。

  • To be frank, you don't even let WCF serialize our DTOs, but use JSON.NET and WCF just send and receive (plain text) JSON, because JSON.NET is simply so much more flexible when it comes to serializing and deserializing data structures. For instance, we use JSON.NET to (de)serialize immutable object structures. Try that with WCF. That will fail miserably.
  • 坦率地说,你甚至不让WCF序列化我们的DTO,但是使用JSON.NET和WCF只发送和接收(纯文本)JSON,因为JSON.NET在序列化和反序列化数据方面简单得多了结构。例如,我们使用JSON.NET(de)序列化不可变对象结构。尝试使用WCF。那将是悲惨的失败。

On top of that we do:

最重要的是我们做:

  • The use of View Model classes to add client functionality.
  • 使用View Model类添加客户端功能。

  • Add custom DataAnnotation validations in the contract assembly to allow validations to run on both the client and the server.
  • 在合同程序集中添加自定义DataAnnotation验证,以允许在客户端和服务器上运行验证。

  • Add an IValidator<T> abstraction (of some sort) to allow either server or client specific validations (by placing implementations in either your business layer or client application).
  • 添加IValidator 抽象(某种)以允许服务器或客户端特定的验证(通过在企业层或客户端应用程序中放置实现)。

  • Transport server specific validation errors back to the client using exceptions.
  • 使用异常将服务器特定的验证错误传回客户端。

#2


2  

You could use your Entities still, but create View Models and put your data annotations on these instead. There's a lot of talk about where to put validation in a project. In general it's almost always a given that it needs to occur at the UI and then usually elsewhere too. I'd avoid trying to centralise it, as this never works out (one size rarely fits all).

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

On the subject of wedging a WCF layer within your solution, unless there is a very good reason for it, I would avoid doing this at all costs. I've seen this sort of thing go wrong many times. It brings a lot of negative effects. In the two commercial cases I have dealt with, you end up with too many endpoints and too much chattiness. It cripples being able to put business logic in your entities and use those methods over-the-wire, makes maintenance a nightmare and without enough hardware and careful design, if hosted on a single server, you may end up having to use named pipes to get the speed you need, which negates any distributed advantage you'd get from using WCF.

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

You would be best to externalise heavy processing tasks as components that you can host elsewhere and communicate through a smaller, more concise interface. In reality apart from image processing, mathematical and scientific applications, heavy data processing doesn't crop up.

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

#3


2  

We use WCF in the manner you describe in your post at my current employer. We ended up having DTO classes for WCF and MVC to communicate with and then ViewModels within the MVC application for model binding and validation within the UI.

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

I agree that having classes that are nearly duplicates of one another and mapping between them is a pain and just seems wrong at some level. From what I've read in the past what we did, and what you may be forced to do, is best practice.

我同意,拥有几乎彼此重复的类并在它们之间进行映射是一种痛苦,在某种程度上似乎是错误的。从我过去所读到的,我们所做的,以及你可能*做的,是最好的做法。

What Adrian proposed above with regard to only having heavy processing done by WCF makes sense as well. Prior to starting my current job I did just that. Most of the business logic was placed in a business layer assembly directly reference by the MVC application. For the few potentially long running processes there were I created WCF services hosted separately that the MVC application communicated with.

Adrian在上面提到的只有WCF进行大量处理的意义也是有道理的。在开始我目前的工作之前,我做到了这一点。大多数业务逻辑都放在MVC应用程序直接引用的业务层程序集中。对于少数可能长时间运行的进程,我创建了单独托管的MVC应用程序与之通信的WCF服务。

Lastly, could you use Web API vs WCF? Web API is lightweight and utilizes HTTP with out all of the overhead that comes with WCF bindings, etc. Additionally, with Web API you could use the same classes the MVC application is using and even utilize model validation within the Web API. This is something I've been working on and becoming more and more common.

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

Hope that helps!

希望有所帮助!

#1


2  

Just like Adrian, I question whether you actually need a WCF service between your DB and an MVC service. This is a much more likely scenario for a client application (Win Forms, WPF) that talks to a database. I'm currently working on a Win Forms project where we use WCF as intermediate layer and we do the following:

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

  • We have an assembly (called 'contract') that is shared between the client and the WCF / BL.
  • 我们有一个在客户端和WCF / BL之间共享的程序集(称为“契约”)。

  • This 'contract' assembly contains all DTOs that are sent over the wire by and to WCF.
  • 该“合同”程序集包含由WCF通过线路发送的所有DTO。

  • We configured the WCF client proxy to use the contract assembly (instead of letting WCF regenerate all DTOs) by setting the 'Reuse types in specified reference assemblies' in the Service Reference Settings.
  • 我们通过在“服务引用设置”中设置“指定引用程序集中的重用类型”,将WCF客户端代理配置为使用合同程序集(而不是让WCF重新生成所有DTO)。

  • We decorate those DTOs with DataAnnotations attributes (and other metadata).
  • 我们使用DataAnnotations属性(和其他元数据)来装饰这些DTO。

  • We don't decorate those DTOs with WCF attributes. WCF doesn't need them to serialize DTOs. They are optional. Leave them out if you can. It just clutters your code.
  • 我们不会使用WCF属性来装饰这些DTO。 WCF不需要它们来序列化DTO。它们是可选的。如果可以,请将它们留下。它只会使你的代码变得混乱。

  • Since the client uses the same assembly we can use DataAnnotations on the client.
  • 由于客户端使用相同的程序集,因此我们可以在客户端上使用DataAnnotations。

  • We validate on the server as well.
  • 我们也在服务器上验证。

  • We use AutoMapper to do most of the boilerplate mapping from entities to DTOs (but never the other way around).
  • 我们使用AutoMapper来完成从实体到DTO的大部分样板映射(但从来没有相反)。

  • To be frank, you don't even let WCF serialize our DTOs, but use JSON.NET and WCF just send and receive (plain text) JSON, because JSON.NET is simply so much more flexible when it comes to serializing and deserializing data structures. For instance, we use JSON.NET to (de)serialize immutable object structures. Try that with WCF. That will fail miserably.
  • 坦率地说,你甚至不让WCF序列化我们的DTO,但是使用JSON.NET和WCF只发送和接收(纯文本)JSON,因为JSON.NET在序列化和反序列化数据方面简单得多了结构。例如,我们使用JSON.NET(de)序列化不可变对象结构。尝试使用WCF。那将是悲惨的失败。

On top of that we do:

最重要的是我们做:

  • The use of View Model classes to add client functionality.
  • 使用View Model类添加客户端功能。

  • Add custom DataAnnotation validations in the contract assembly to allow validations to run on both the client and the server.
  • 在合同程序集中添加自定义DataAnnotation验证,以允许在客户端和服务器上运行验证。

  • Add an IValidator<T> abstraction (of some sort) to allow either server or client specific validations (by placing implementations in either your business layer or client application).
  • 添加IValidator 抽象(某种)以允许服务器或客户端特定的验证(通过在企业层或客户端应用程序中放置实现)。

  • Transport server specific validation errors back to the client using exceptions.
  • 使用异常将服务器特定的验证错误传回客户端。

#2


2  

You could use your Entities still, but create View Models and put your data annotations on these instead. There's a lot of talk about where to put validation in a project. In general it's almost always a given that it needs to occur at the UI and then usually elsewhere too. I'd avoid trying to centralise it, as this never works out (one size rarely fits all).

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

On the subject of wedging a WCF layer within your solution, unless there is a very good reason for it, I would avoid doing this at all costs. I've seen this sort of thing go wrong many times. It brings a lot of negative effects. In the two commercial cases I have dealt with, you end up with too many endpoints and too much chattiness. It cripples being able to put business logic in your entities and use those methods over-the-wire, makes maintenance a nightmare and without enough hardware and careful design, if hosted on a single server, you may end up having to use named pipes to get the speed you need, which negates any distributed advantage you'd get from using WCF.

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

You would be best to externalise heavy processing tasks as components that you can host elsewhere and communicate through a smaller, more concise interface. In reality apart from image processing, mathematical and scientific applications, heavy data processing doesn't crop up.

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

#3


2  

We use WCF in the manner you describe in your post at my current employer. We ended up having DTO classes for WCF and MVC to communicate with and then ViewModels within the MVC application for model binding and validation within the UI.

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

I agree that having classes that are nearly duplicates of one another and mapping between them is a pain and just seems wrong at some level. From what I've read in the past what we did, and what you may be forced to do, is best practice.

我同意,拥有几乎彼此重复的类并在它们之间进行映射是一种痛苦,在某种程度上似乎是错误的。从我过去所读到的,我们所做的,以及你可能*做的,是最好的做法。

What Adrian proposed above with regard to only having heavy processing done by WCF makes sense as well. Prior to starting my current job I did just that. Most of the business logic was placed in a business layer assembly directly reference by the MVC application. For the few potentially long running processes there were I created WCF services hosted separately that the MVC application communicated with.

Adrian在上面提到的只有WCF进行大量处理的意义也是有道理的。在开始我目前的工作之前,我做到了这一点。大多数业务逻辑都放在MVC应用程序直接引用的业务层程序集中。对于少数可能长时间运行的进程,我创建了单独托管的MVC应用程序与之通信的WCF服务。

Lastly, could you use Web API vs WCF? Web API is lightweight and utilizes HTTP with out all of the overhead that comes with WCF bindings, etc. Additionally, with Web API you could use the same classes the MVC application is using and even utilize model validation within the Web API. This is something I've been working on and becoming more and more common.

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

Hope that helps!

希望有所帮助!