简体   繁体   English

ASP.NET MVC - 模型的WCF类

[英]ASP.NET MVC - WCF Classes for Models

ASP.NET | ASP.NET | MVC 4 | MVC 4 | C# | C#| WCF WCF

I am using WCF web services as an intermediary from the presentation layer (MVC) to the data layer (Entity). 我使用WCF Web服务作为从表示层(MVC)到数据层(实体)的中介。 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. 为了简化将数据模型数据从MVC移动到Web服务,我想我会在WCF中使用代理类,因此会有一个集中式类。 Unfortunately, this caused the loss of MVC decorations on properties within the model. 不幸的是,这导致模型中属性上的MVC装饰丢失。 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? 有没有一种好方法可以创建一个集中式类用于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. 一个在MVC端,一个在WCF端。 Which would still require me to make a change on both sides if a property changed in a class. 如果某个类中的属性发生变化,那么仍需要我对双方进行更改。

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. 如果我想更新此记录,则将该类发送到WCF服务,映射到适当的实体框架类,并保存到数据库。 To simplify the transfer I thought I would just put this class in the WCF project and reference it in the MVC project. 为了简化传输,我想我会把这个类放在WCF项目中并在MVC项目中引用它。 Then I could pass the class back in forth between WCF and MVC. 然后我可以在WCF和MVC之间传回这个类。 Also, if I updated the class in WCF then it would be reflected in MVC. 此外,如果我在WCF中更新了类,那么它将反映在MVC中。 That's what is meant by centralized. 这就是集中化的意思。

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. 一般来说,它几乎总是给定的,它需要在UI上发生,然后通常在其他地方发生。 I'd avoid trying to centralise it, as this never works out (one size rarely fits all). 我会避免试图集中它,因为这永远不会成功(一种尺寸很少适合所有)。

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. 在您的解决方案楔入WCF层,除非有很好的理由为它的主题,我会不惜一切代价避免这样做。 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获得的任何分布式优势。

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. 实际上,除了图像处理,数学和科学应用之外,不会出现繁重的数据处理。

We use WCF in the manner you describe in your post at my current employer. 我们以您在当前雇主的帖子中描述的方式使用WCF。 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和MVC的DTO类与MVC应用程序中的ViewModels进行通信,以便在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. Adrian在上面提到的关于WCF只进行大量处理的建议也是有道理的。 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. 大多数业务逻辑都放在由MVC应用程序直接引用的业务层程序集中。 For the few potentially long running processes there were I created WCF services hosted separately that the MVC application communicated with. 对于少数可能长时间运行的进程,我创建了单独托管的MVC应用程序与之通信的WCF服务。

Lastly, could you use Web API vs WCF? 最后,您可以使用Web API与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. Web API是轻量级的,并且利用HTTP来消除WCF绑定等所带来的所有开销。此外,使用Web API,您可以使用MVC应用程序使用的相同类,甚至可以在Web API中使用模型验证。 This is something I've been working on and becoming more and more common. 这是我一直在努力并变得越来越普遍的事情。

Hope that helps! 希望有所帮助!

Just like Adrian, I question whether you actually need a WCF service between your DB and an MVC service. 就像Adrian一样,我怀疑你是否真的需要在你的数据库和MVC服务之间使用WCF服务。 This is a much more likely scenario for a client application (Win Forms, WPF) that talks to a database. 对于与数据库进行通信的客户端应用程序(Win Forms,WPF),这种情况更为可能。 I'm currently working on a Win Forms project where we use WCF as intermediate layer and we do the following: 我目前正在开发一个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属性装饰这些DTO。 WCF doesn't need them to serialize DTOs. WCF不需要它们来序列化DTO。 They are optional . 它们是可选的 Leave them out if you can. 如果可以,请将它们留下。 It just clutters your code. 它只是使你的代码混乱。
  • 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. 坦率地说,你甚至不让WCF序列化我们的DTO,但是使用JSON.NET和WCF只发送和接收(纯文本)JSON,因为JSON.NET在序列化和反序列化数据方面简单得多了结构。 For instance, we use JSON.NET to (de)serialize immutable object structures. 例如,我们使用JSON.NET(de)序列化不可变对象结构。 Try that with WCF. 尝试使用WCF。 That will fail miserably. 那将是悲惨的失败。

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<T>抽象(某种)以允许服务器或客户端特定的验证(通过在企业层或客户端应用程序中放置实现)。
  • Transport server specific validation errors back to the client using exceptions. 使用异常将服务器特定的验证错误传回客户端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM