Tuesday, January 20, 2015

Debugging exception in WCF IsOneWay=True WCF Services

Recently I had to work on an one way WCF service. The scenario is little different than normal service hosting. There are many services hosted in a server machine using IIS WAS hosting.All of those expose same contact interface. The URLs are obviously different but they follow certain convention such as

net.pipe://localhost/{feature name}/service.svc

The caller has some logic to prepare the above url and it simply calls the service. It uses fire and forget method by decorating contract with IsOneway=True. Below is a similar contract.


[OperationContract(IsOneWay = true)]
void InvokeAsync(Dictionary<stringobject> messageInfoDictionary);

After setting up the environment, we started facing one issue. The service implementation is not getting executed. But there is no exception in caller side. In a normal scenario we immediately go to the svclog file, if there is an exception. As there was no exception, the investigation didn't turn into svclogs in the first round.

Analyzed each and every bit of caller code where the url is prepared. No problem at all. Checked the contract methods again and again for any mismatch. Its all perfect. Finally decided to turn on the svclogs in caller side on the assumption that client is not able to establish communication with server.

It shows that there is timeout. But it didn't help to identify the root cause. Then enabled server side svclogs and it helped.

The exception was System.ServiceModel.Dispatcher.NetDispatcherFaultException .It has an inner exception as well which is of type System.Runtime.Serialization.SerializationException. The error message was

"Element 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:Value' contains data from a type that maps to the name 
'http://schemas.datacontract.org/2004/07/{Namespace}:Message'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'Message' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer."

Yes its clear the data contract class is in different assembly and that assembly is not available in the bin folder of service. Putting the dll in place fixed the issue.

I am more researching on how these kind of issues can be caught in our code and log properly. This is important as the services which are exposing the same contract are going to be developed by different  and disconnected teams.

Tuesday, January 13, 2015

Can my business object / entity / model class contain Save()?

This is a very old question. Lets try to answer it with the mind of a passionate programmer who wants his code to be the best quality code. Here we will be examining different possibilities and understand why some techniques are not recommended.

What if the Save() is part of my entity class?

Lets think in the way that, the Save() is part of the business object. What are the pros and cons

Pros

  1. Data and the functions manipulating it are in single unit and its encapsulated.

Cons

  1. If we want to change the data persistence mechanism from SQL Server database to XML, we want to modify all the entity classes.
  2. Violation of SRP - The class will change for 2 reasons. If a new property added or persistence mechanism changed.

What if the Save() is moved to Repository class

Here the Save() will be part of another class. Lets call that class as Repository. Pros and cons below

Pros

  1. Underlying storage mechanism can change without a change in the entity class.

Cons

  1. Repository might need separate methods to save different entities such as SaveEmployee() SaveOrder() etc...Otherwise one method which accepts base class of entity classes and use reflection to identity the properties to be saved. Need to keep track of what property maps to what field in database or node in xml.
  2. The consumer of the entity classes needs to remember one more class name to work with entities. API cannot be explored by developers. Need documentation.

What if the Save() is available in entity and repository and they are loosely connected?


In this technique, Save() will be available in entity class as well as repository class. The difference here is, the entity class method body will not contain any logic to persist the data. It just pass the execution to the repository. The repository knows how to persist. Some code snippet below

Core classes

public abstract class EntityBase
    {
        public abstract void Save();
    }
    interface IRepository
    {
        void Save(EntityBase entity);
    }
    static class RepositoryFactory
    {
        public static IRepository Get()
        {
            IRepository repository=default(IRepository);
            //Logic to decide repository based on config or any other criteria.
            return repository;
        }
    }

Below are the application specific classes.

    public class Account:EntityBase
    {
        public string Name { getset; }
        public decimal balance { getset; }
        public override void Save()
        {
            RepositoryFactory.Get().Save(this);
        }   
    }
 
    class SqlServerRepository:IRepository
    {
        void IRepository.Save(EntityBase entity)
        {
            //Use reflection to get the properties to be saved.
            //Or need to have separate methods like SaveAccount(), SaveCustomer() in the repository.
        }
    }
    //The UI parts. It can be the controller in case of MVC.
    class AccountViewmodel
    {
        Account acc = new Account() { Name = "Sales", Balance = 30000 };
        void SaveCommand()
        {
            acc.Save();
        }
    }

I know this is not a production ready code. But this gives idea how the Save() method can be written by honoring the SRP and keeping the easiness of API usage.