I need to return Employee class as a response to my clientA as follows.
[OperationContract]
public Employee GetEmployee(String id)
{
..
..
return emp;
}
public class Employee
{
public string Name;
public string phoneNo;
}
But the problem here is clientB is going to consume my service but the need a SSN of employee. If i add it into Employee class, I will be sending to clientA as well which wont need it. How to overcome this situation. If i have to do anything with custom deserialization, would not it be a problem if i about to handle 1000s of properties?
Which is the better solution? Any wcf architectural help would also be more helpful.
If different clients have different needs, the proper thing is to create different services as well.
You put the business logic in a shared business class (or distributed over multiple shared business classes), and expose a different service per different type of client. That keeps things nice, abstracted and secure, and nobody gets data they don't need or want.
There has been a quite similar discussion on this link. Basically, it refers to conditional hiding the value of a data member.
You could decide if you want to expose a data member based on the client id or credentials (which should be passed as a parameter to the service method call).
[OperationContract]
public Employee GetEmployee(int clientId, String id)
{
var employee = new Employee();
//here you might use a mapping table between the clients and the exposed data members
if (clientId == 1)
{
employee.IsSSNSerializable = true;
}
return employee;
}
The Employee class will expose the SSN based on the value of the IsSSNSerializable property:
[DataContract]
public class Employee
{
public bool IsSSNSerializable = false;
[DataMember]
public string Name;
[DataMember]
public string phoneNo;
public string SSN;
[DataMember(Name = "SSN", EmitDefaultValue = false)]
public string SSNSerializable
{
get
{
if (!IsSSNSerializable)
return null;
return SSN;
}
set
{
SSN = value;
}
}
}
I would suggest you take a read of the versioning strategies of the WCF that might be matches with your scenarios.
for my case, i implemented IExtensibleDataObject on the data contracts and manage in this layer instead of service contracts layer.
the downside would be difficulties to track different versions of contracts, however I'm practicing the semi-strict versioning and works well for me.
I second Roy, but however if this is the only difference between client A and B. It would not hurt to expose a GetEmployee method with parameter IsSSNRequired which can have a default false value.
Related
I was wondering if there was a more elegant way in managing contact details for an individual. Forget the SQL side of things for a moment, I am intrigued in how one would perhaps attempt to drive this via a DDD approach.
I was fooling around with some code in an effort to get comfortable with DDD as a whole and came up with the following which seems awful.
Firstly, I have an object called Person (simplified for the purpose of this post) where I envision methods to add and essentially manage different methods of communicating an individual.
public class Person
{
public Person()
{
this.ContactDetails = new List<ContactDetails>();
}
public void AssociateContactDetails(ContactDetails contactDetails)
{
var existingContactDetails = this.ContactDetails.FirstOrDefault(x => x.ContactType == contactDetails.ContactType);
if (existingContactDetails != null)
{
this.ContactDetails.Remove(existingContactDetails);
}
this.ContactDetails.Add(contactDetails);
}
public IList<ContactDetails> ContactDetails { get; private set; }
}
Two approaches spring to mind. One where I have a fairly simple object like the one below which is quite generic (using the term loosely).
public enum ContactType
{
Email, Telephone, Mobile, Post
}
public class ContactDetails
{
private readonly ContactType contactType;
private readonly string value;
public ContactDetails(ContactType contactType, string value)
{
this.contactType = contactType;
this.value = value;
}
public ContactType ContactType
{
get { return this.contactType; }
}
public string Value
{
get { return this.value; }
}
}
But then I put myself into a corner with this approach as although it works well for trivial items such as email and telephone, when it comes to something like postal a string doesn't quite cut it. Therefore, after this I am heading towards the approach of having each mechanism of communication to represented by its own type, i.e.:
public class Post
{
public Address PostalAddress { get; set; }
}
public class Mobile
{
public string MobileNo { get; set; }
}
public class Telephone
{
public string AreaCode { get; set; }
public string TelephoneNo { get; set; }
}
public class Email
{
public string EmailAddress { get; set; }
}
Each type can then represented as a collection or single instance in the Person class? Seems long winded however is perhaps more readable and maintainable.
The question I guess is if there is a more elegant way in implementing such a feature and whether someone can point me in the direction of a good example similar to this. I imagine this is a common thing / problem to overcome.
Cheers, DS.
We know for sure what are the contact methods "email, "phone" and "address", so having identified those what we have to do first is to model those concepts taking into account what they really are. Let's take "email" as example and see what it really is in order to model it properly. It is a value object (an immutable object) that once created it will never change just as an integer number is an immutable object as well. The difference is that for modelling an integer number we can use the int type provided by any programming language, but the question is what class do we use for modelling en Email? Most of people would use a String instance to model an Email, but is this OK? In order to answer it let's see what is the protocol (the set of messages) a String object knows to response: "charAt(anIndex), replace(aString, anotherString), etc... ". Imagine that if we model an email by using a String class we could ask the email "replace(aString, anotherString)". That sounds weird, that message should not be part of the behavior an email should expose to other objects. Also so so important we said an email is immutable to it cannot expose behavior that at the end change it state. So it makes visible that we need to create a whole new abstraction to model an email and what is it? The Email class finally comes in!!! I know you suggested it but I just wanted to let you see why we need an Email class created.
First of all this is DDD (object oriented) so FORGET avoid setters and getters. In the email class you created you expose a setter method meaning that you can change the email and it contradicts with the nature of what an email is (immutable). An email is immutable from the momento it is created:
Email.fromString("monicalewinsky#gmail.com");
that is the same as doing
new Email("monicalewinsky#gmail.com");
The fromString method is a factory method that adds semantic to our domain model. This is very common in smalltalk instead of calling the constructor directly. Are we done??? Not at all. An email instance should be created as long as it is valid so the email class should assert the string from which is created is valid:
Email(String anEmailStringRepresentation) {
assertIsValid(anEmailStringRepresentation);
}
assert is valid should verify it is actually an email string representation. This is that is has only one # character, its local part is valid and then its domain part is valid. You can check the wikipedia for email address to understand better how it is composed.
Remember always that programming is a learning process, as long as we understand a domain better and better we reflect that domain in the code and it always must be consistent with the real world! Our Email class should look like more or less like:
class Email {
String value;
Email(aString) {
value = aString;
}
public String getLocalPart()
public String getDomainPart()
public String asString()
public boolean equals(anObject)
public static Email fromString(aString)
}
That's it. It happens the same with PhoneNumber. It is also an inmmutable object and you should create a class with its own protocol. Remember never use set/get as you showed up if we are doing DDD. I don't think you need two value objects Telephone and Mobile since those are polymorphic objects and you could model a mobile phone number or a home phone number with the TelephoneNumber abstraction. It's like modelling a credit card. At the end you will end up and understand that the class CreditCard is enough and a better design than having several class such as Visa, MasterCard, and so on.
Let's skip the Address class and let's go back to your problem now.
So far we have identified and created properly all the value objects we need. Now we need to create an abstraction for representing an email, phonenumber, address as contact methods and if we keep loyal to the domain language we could say:
ContactMethod.for(Email.fromString("monica#gmail.com"));
or
ContactMethod.for(PhoneNumber("34234234234"));
etc
so our ContactMethod would look like:
class ContactMethod {
static EMAIL = 1;
static PHONE_TYPE = 2;
static ADDRESS_TYPE = 3;
String type;
String value;
ContactMethod(int aType, String aValue) {
type = aType;
value = aValue;
}
String getType()
String getValue()
public static ContactMethod at(Email anEmail) {
return new ContactMethod(EMAIL, anEmail.asString());
}
public static ContactMethod at(PhoneNumber aPhoneNumber) {
return new ContactMethod(PHONE_TYPE, aPhoneNumber.asString());
}
public static ContactMethod at(Address anAddress) {
return new ContactMethod(ADDRESS_TYPE, anAddress.asString());
}
}
See that ContactMethod is also an immutable class, actually a rule of thumb is that an Aggregate root should have ideally only an aggregation of value objects.
This is finally how your Person class would look like:
class Person {
List<ContactMethod> contactMethods;
contactedAt(Email anEmail) {
contactMethods.add(ContactMethod.at(anEmail));
}
contactedAt(PhoneNumber aPhoneNumber) {
contactMethods.add(ContactMethod.at(aPhoneNumber));
}
contactedAt(Address anAddress) {
contactMethods.add(ContactMethod.at(anAddress));
}
}
On my journey of learning DDD sometimes I see patterns instead of problems... an interesting example Everything seems to be an Aggregate Root is another answer I had provided regarding a menu, which had different categories such as starter, main, desert etc.
I had modeled this implicitly as a category string. After i posted there was a second answer where someone suggested modeling these as explicit lists of:
Menu {
List<Food> starters;
List<Food> entrees;
List<Food> desserts;
List<Food> drinks;
}
In this way, the entire concept of the category for a food was removed, this was enlightening for me and saw a different way of modeling and in this case reducing complexity.
My view is to try and model the code so that if I sat down with the business expert (who is not a developer) and showed them the use case code from a high level person.SetMobileNumber("078321411", Countries.UK) they would be able to understand it:
public void HandleUpdateMobileCommand(UpdateMobileNumber command)
{
// repositories, services etc are provided in this handler class constructor
var user = this.UserRepository.GetById(command.UserId);
user.SetMobile(command.number, command.country);
this.UserRepository.Save(user);
// send an SMS, this would get the number from user.Mobile
this.SmsService.SendThankYouMessage(user);
}
Or even better, you could have a MobileUpdated event get fired when you update the user mobile, to which some code somewhere else (which is an expert on sending SMS messages, and nothing else) is listening to these events - for me this is the real power of DDD of breaking down code in to expert systems.
So in summary, I think your second suggestion of explicitly modeling with Post, Mobile, Landline and Email makes most sense.
I wouldn't say this a DDD domain or not as there isn't enough information on any complex logic (or multi-user race conditions) that you require, just to mention don't forget that you may be better writing a CRUD app if that makes more sense in this situation.
There's this central idea in DDD that domain modelling must take shape through discussion with domain experts. If you're making up these class names out of thin air, chances are they won't exactly match your real domain. Trivial ones such as Email or Telephone should be correct, but maybe for others you want feedback from an expert first.
Generally speaking, it's a good idea indeed to favor semantically rich modelling with dedicated value objects over primitive types. In C# it comes at a cost though since the amount of boilerplate code needed is huge (unlike F# for instance). This is why I usually prefer to do it only when the type has more than a single property or when there are specific construction rules or invariants to it.
One good thing you can do is model your types as immutable Value Objects. So something like:
public class Telephone
{
public string AreaCode { get; set; }
public string TelephoneNo { get; set; }
}
Might become:
public class TelephoneNumber
{
private string areaCode;
private string subscriberNumber;
private TelephoneNumber()
{
}
public TelephoneNumber(string areaCode, string subscriberNumber)
{
this.AreaCode = areaCode;
this.SubscriberNumber = subscriberNumber;
}
public string AreaCode
{
get
{
return this.areaCode;
}
private set
{
if (value == null)
{
throw new ArgumentNullException("AreaCode");
}
if ((value.Length <= 0) || (value.Length > 5))
{
throw new ArgumentOutOfRangeException("AreaCode");
}
this.areaCode = value;
}
}
// Etc.
}
I'm having difficulty fully grasping a particular function of Windows Communication Foundation. I've read tutorial after tutorial, book after book. So the entire conceptual nature I feel confident on.
Except for one part; this is the part that is almost like magic. Which actually made the learning slightly difficult.
I'll use the most common example on the web.
I'll start with the DataContract:
[DataContract]
public class Customer
{
// Declerations:
private Guid id;
private string firstName;
private string lastName;
private string emailAddress;
[DataMembers]
public Guid Id
{
get { return id; }
set { id = value; }
}
[DataMember]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
[DataMember]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
[DataMember]
public string EmailAddress
{
get { return emailAddress; }
set { emailAddress = value; }
}
}
Now I've created an object; that I'd like to be exposed to my Client.
So I then create my ServiceContract.
[ServiceContract]
public interface ICustomer
{
[OperationContract]
Customer AddCustomer(Customer info);
}
So this where I keep confusing myself; lets say you have a Client-Side Application. You've consumed the service. You have three textboxes in a separate Assembly / Namespace. The Client puts in the criteria:
First Name
Last Name
Email Address
If you set those text boxes to the date; they will transfer over in Metadata. But on the server; how can I pull that information variable out? Do I just reference the private Guid and private string variables?
I saw a tutorial on how to add it to a database; but I don't fully comprehend what WCF is actually doing. Which is similar to what I'd like. I'd like to get the Client interface input and write it to a database and a separate log file.
I could just follow the tutorial; but I want to know how the Customer object data and it's variables are being assembled for use on the server.
Any assistance would be amazing, some clarification.
Sorry if my question is stupid; I'm not trying to start a debate. Just want to understand how to pull those variables and use them on the server.
Thanks in advance. If I didn't format the question correctly please let me know. I'd really like to understand what it is conceptually doing.
Update:
My true intention is to understand how the Client interface references that object; so when the call is made the server has a valid object that isn't null.
Client types in text box ---> Proxy Sends ---> De-serialized ---> Service ---> Serializes ---> Makes Property available for usage.
The actual types, such as your Customer class are not really transmitted across the wire. However, the public information within those types is sent across through a process called serialization. Serialization allows a type to be represented in a way that allows it to be transmitted over a network. This is often expressed using a format such as SOAP, JSON or XML. WCF even allows you to control exactly how objects are serialized, allowing you to write your own formatter if you want. Basically, when AddCustomer is called, WCF is constructing a Customer object on the server, serializing it, and sending those bits across the wire.
Now, on the client you would have a matching Customer object called a proxy. It might look something like:
public class Customer
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
}
Basically, a scaled down version with just the data members of the server version, with no code or logic. On the client, the serialized representation of Customer is deserialized back into an instance of this local proxy class, where it can be used for various client purposes, including being bound to local UI elements.
Web services can expose this type information using WSDL (which is an XML format for describing a web service contract). Visual Studio (using the wsdl.exe tool) can automatically write these proxy classes for you, which makes everything just work magically.
I am not sure but may be this is what you are looking for
Data Transfer and Serialization
In particular you can check DataContractSerializer
You can check this article too : Serialization in Windows Communication Foundation
As a beginner to WCF i want to implement a call to the Active Directory Service which gets all Users, the method looks like this:
[OperationContract]
SearchResultCollection GetAllUsers();
SearchResultCollection is not serializable so i have to make something like this:
[DataContract]
SearchResultCollection
So i have to make my own wrapper class which inherits the SearchResultCollection or use IDataContractSerializer. Both solutions seems not easy.
The question: How is the "standard" approach to use .NET Classes as a return type in a WCF service?
(Writing a own DataContract for my own class seems easy. ;))
The DataContract route will suffice here. The standard way is to decorate your class with the relevant attributes and it will be consumable by WCF in methods:
[DataContract]
public sealed class CustomerResponse
{
[DataMember]
public Guid CustomerReference { get; set; }
}
[ServiceContract]
public interface IWcfMessagingService
{
[OperationContract]
CustomerResponse GetCustomer();
}
If the class is not serializable, I don't think even wrapping it will work.
However, the SearchResultCollection is itself returned from a WCF method, so you could just pass that straight through your own service, or at the very least, wrap it successfully.
I think your best bet is create your own simple POCO class to represent SearchResult, and return a list of these objects. Really you want to be able to control exactly the information you need to send back from the service. For example:
[Serializable]
public class MySearchResult
{
public string Name { get; set; }
public string Email { get; set; }
}
And simply iterate the searech results and pull out the properties you need like so:
var results = new List<MySearchResult>();
foreach (SearchResult r in searchResultCollection)
{
results.Add(new MySearchResult
{
Name = searchResult.Properties["Name"],
Email = searchResult.Properties["Email"]
});
}
That way the xml being sent back isn't bloated with all the properties you don't need AND you can serialize your own List<MySearchResult> return results. And by the way I have no idea if the Name and Email properties exist I am just showing an example.
I think I would just return a List of User where User is a custom User class flagged as Serializable. The method that gets the data from active directory can populate the User class by looping through the result.
I am trying to figure out what is the difference between IExtensibleDataObject and IExtensibleObject.
MSDN say that the first one (IExtensibleDataObject) is to let the deserialization of object that may have added attribute and the second one (IExtensibleObject) look very similar, it does let the object add attribute too.
I am confused.
IExtensibleDataObject is about serialization, and it can be used outside of WCF's service stack. Its main purpose is round-tripping different versions of a data contract without losing information. For example, on the first version of your contract, you have this type:
[DataContract(Name = "Person")]
public class Person : IExtensibleDataObject {
ExtensionDataObject IExtensibleDataObject.ExtensionData { get; set; }
[DataMember(Order = 0)] public string Name;
[DataMember(Order = 1)] public int Age;
}
You deploy your services with this data type, and you have some clients using this type. Some service operations return a Person to the client, and the client can send those objects back to the service, as in the example below.
[ServiceContract]
public interface ITest {
[OperationContract] Person[] GetAllPeople();
[OperationContract] void DoSomething(Person person);
}
It all works great, until a change in the business logic requires that a new member to be added to Person, and a backing database requires that field to be present (not null).
[DataContract(Name = "Person")]
public class Person_V2 : IExtensibleDataObject {
ExtensionDataObject IExtensibleDataObject.ExtensionData { get; set; }
[DataMember(Order = 0)] public string Name;
[DataMember(Order = 1)] public int Age;
[DataMember(Order = 2)] public string Address;
}
Without IExtensibleDataObject, the existing clients would receive the Person object, fill its Name / Age property and promptly discard the Address element passed to it. And when it called the DoSomething method with that object, it would pass an instance which would be invalid at the server (Address would be null).
What IEDO does is enable this scenario, where existing (legacy) clients can continue receiving new versions of data contracts from the service - the client will fill the fields it understands with the data from the service, and those elements which it doesn't understand will be stored in the ExtensionDataObject so that they can be reserialized later. In the example above, the legacy clients will only be able to read the Name and Age properties of the Person, but when it sends the object back to the server, the serialized data will contain all three properties.
That was a long story about IEDO. IExtensibleObject does not have anything to do with serialization - is about hooking up extensions to some pre-defined objects in the WCF service stack (the host, the operation context, the instance context and the context channel). Not as interesting as IEDO, so I'll stop for here :)
Edited: for completeness sake, if you want more information about IExtensibleObject, you can check the post at http://blogs.msdn.com/b/carlosfigueira/archive/2012/01/31/wcf-extensibility-iextension-and-iextensibleobject.aspx.
IExtensibleDataObject is for accommodating extra data in a service message (perhaps data that wasn't specified by the contract when proxies were generated).
IExtensibleObject is used to extend certain aspects of the WCF engine (Such as ServiceHostBase and InstanceContext).
The names sound similar, but they are simply different interfaces for different purposes.
I'm prototyping a tool that will import files via a SOAP api to an web based application and have modelled what I'm trying to import via C# interfaces so I can wrap the web app's model data in something I can deal with.
public interface IBankAccount
{
string AccountNumber { get; set; }
ICurrency Currency { get; set; }
IEntity Entity { get; set; }
BankAccountType Type { get; set; }
}
internal class BankAccount
{
private readonly SomeExternalImplementation bankAccount;
BankAccount(SomeExternalImplementation bankAccount)
{
this.bankAccount = bankAccount;
}
// Property implementations
}
I then have a repository that returns collections of IBankAccount or whatever and a factory class to create BankAccounts for me should I need them.
My question is, it this approach going to cause me a lot of pain down the line and would it be better to create POCOs? I want to put all of this in a separate assembly and have a complete separation of data access and business logic, simply because I'm dealing with a moving target here regarding where the data will be stored online.
This is exactly the approach I use and I've never had any problems with it. In my design, anything that comes out of the data access layer is abstracted as an interface (I refer to them as data transport contracts). In my domain model I then have static methods to create business entities from those data transport objects..
interface IFooData
{
int FooId { get; set; }
}
public class FooEntity
{
static public FooEntity FromDataTransport(IFooData data)
{
return new FooEntity(data.FooId, ...);
}
}
It comes in quite handy where your domain model entities gather their data from multiple data contracts:
public class CompositeEntity
{
static public CompositeEntity FromDataTransport(IFooData fooData, IBarData barData)
{
...
}
}
In contrast to your design, I don't provide factories to create concrete implementations of the data transport contracts, but rather provide delegates to write the values and let the repository worry about creating the concrete objects
public class FooDataRepository
{
public IFooData Insert(Action<IFooData> insertSequence)
{
var record = new ConcreteFoo();
insertSequence.Invoke(record as IFooData);
this.DataContext.Foos.InsertOnSubmit(record); // Assuming LinqSql in this case..
return record as IFooData;
}
}
usage:
IFooData newFoo = FooRepository.Insert(f =>
{
f.Name = "New Foo";
});
Although a factory implementation is an equally elegant solution in my opinion. To answer your question, In my experience of a very similar approach I've never come up against any major problems, and I think you're on the right track here :)