Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC - WCF Classes for Models

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?

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.

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

[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.

like image 722
Will Avatar asked Sep 10 '13 21:09

Will


2 Answers

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:

  • We have an assembly (called 'contract') that is shared between the client and the WCF / BL.
  • This 'contract' assembly contains all DTOs that are sent over the wire by and to WCF.
  • 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.
  • We decorate those DTOs with DataAnnotations attributes (and other metadata).
  • 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.
  • Since the client uses the same assembly we can use DataAnnotations on the client.
  • 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).
  • 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.

On top of that we do:

  • The use of View Model classes to add client functionality.
  • Add custom DataAnnotation validations in the contract assembly to allow validations to run on both the client and the server.
  • 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).
  • Transport server specific validation errors back to the client using exceptions.
like image 97
Steven Avatar answered Sep 28 '22 04:09

Steven


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).

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.

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.

like image 23
Adrian Thompson Phillips Avatar answered Sep 28 '22 05:09

Adrian Thompson Phillips