Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Friday, 29 April 2016

How to verify that a class is serializable?

Recently I've came into investigating a failing End-to-End test that was failing inside the WCF service with an exception. The exception was related to WCF serialization of the return type of the service. As usually I decided to tackle this issue in the TDD way:

  1. Write a fialing test that reproduces the issue
  2. Write the minimum amount of code to make the test pass
  3. Refactor if needed

I already had a failing End to End test that was failing, but it was a heavy and complex test. All I wanted to a small, fast, isolated and reproducible test that would test only the serialization of that class. We're using FluentAssertions library for readable and intuitive assertions in our unit tests I checked whether it contains a way to verify whether a class would be successfully serialized in WCF. Unfortunately, it had two similar methods:

I need to explain what these methods exactly do for those who are not familiar with them:

  1. Serialize the instance using the selected serialization method: binary or XML
  2. Deserialize the result of the above serialization
  3. Compare the values of the resulted instance with the original one
It was exactly what I needed, but these methods use different serialization methods than WCF. WCF uses DataContract serialization. I decided to contribute to FluentAssertions library and to add the required method. Dennis Doomen generously accepted my pull request and the new method is available in the official nuget package starting from version 4.5.0. Here how it looks like with the new method:


Last but not least: if you encounter into WCF serialization issues, take a look at my post from 2010 with some WCF Serialization Tips.


Thursday, 20 February 2014

How to follow best practices of NHibernate with WCF integration?

If you work with NHibernate, you are probably familiar with its best practices. When working with WCF we need to maintain UnitOfWork and transactions. There is a library that makes this integration seamless: NHJump by James Lanng and Richard Penrose.

Marking your service class with an attribute will do the magic:
  • will create a unit of work per request
  • will open a transaction
  • will commit it at the end of the request or rollback it if an exception was thrown
 [ServiceContract] 
public interface IPersistenceService  {  ...  }  
[UnitOfWork]
public class PersistenceService : IPersistenceService  {  ...  }

Sounds nice? It has also ASP.NET MVC integration.

Samples can be found on SVN repository:

Available on nuget:

PM> Install-Package NhJump.Persistence

Sunday, 29 January 2012

How to monitor WCF Service up time using Performance Counters?

I was asked to monitor how long WCF service is up using Performance Counters. There is no WCF specific counter that displays this. Actually it depends on the hosting of your WCF service.

- If the service is hosted in IIS, use "Service Uptime" performance counter under "Web Service Category"
- If the service is hosted in Console application or Windows Service, you can use "Elapsed Time" in "Process" category

Thanks to Josef Pfleger for answering my question

Thursday, 17 November 2011

There was a problem loading the XSD documents provided: a reference to a schema element with name X and namespace Y could not be resolved because the element definition could not be found in the schema for targetNamespace Z.

Posting this one mostly as a reminder for myself:

I was working on extending some existing WCF service in development, while an older version already deployed to production. Let's say our production site is
www.borismod.com
and my local machine name is borism
When I tried to create a local proxy of the web service I got the following error:

(all the ULRs and namespaces are fictive)

>svcutil http://www.borismod.com/RealGeekyURL/mex

Attempting to download metadata from 'http://www.borismod.com/RealGeekyURL/mex' using WS-Metadata Exchange or DISCO.
Error: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: There was a problem loading the XSD documents provided: a reference to a schema element with name 'DoSomeCrazyGeekyStuff' and namespace 'http://borismod.blogspot.com/' could not be resolved because the element definition could not be found in the schema for targetNamespace 'http://www.borismod.com/'. Please check the XSD docu
ments provided and try again.
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://www.borismod.com/']/wsdl:portType[@name='ISomeRealGeekService']

Problem:
The actual problem is that there are references from the WSDL to some internal classes. The references point to the production site. The new added classes were missing in production.

Solution:
Point in host file to the local machine, actually adding the following line in hosts file:
127.0.0.1 www.borismod.com

Tuesday, 9 February 2010

WCF Serialization Tips

Here are a few tips on how to improve WCF performance and traffic by simple putting the right attributes on your serializable classes:


1. "Avoid inferred data contracts (POCO). Always be explicit and apply the DataContract attribute" (C) Juval Löwy
2. "Use the DataMember attribute only on properties or read-only public members" (C) Juval Löwy
3. Mark [DataMember] only properties, that DO have to be serialized. Avoid marking calculated properties as DataMember
2. Consider using (IsReference = true) on classes to avoid data duplication and circular references.
3. Use short (one or two letters) Name on classes and properties to significantly reduce traffic. (C) Eyal Vardi
4. Specify short Value for EnumMember
5. Use parametrized DataContract property for generic classes
6. Use (EmitDefaultValue=false) on properties to reduce traffic

Sample:

[DataContract(Name="CT")]
  public enum CustomerTypes
  {
    [EnumMember(Value = "I")]
    Internal,
    [EnumMember(Value = "E")]
    External,
    [EnumMember(Value = "U")]
    Unknown
  }

  [DataContract(IsReference = true, Name = "B{0}")]
  public class BusinessBase<T>
  {
    T Id { get; set; }
  }

  [DataContract(IsReference = true, Name = "C")]
  public class Customer : BusinessBase<int>
  {
    [DataMember(Name="C", EmitDefaultValue=false)]
    public CustomerTypes CustomerType { get; set; }

    [DataMember(Name = "N", EmitDefaultValue = false)]
    public string Name { get; set; }

    [DataMember(Name = "P", EmitDefaultValue = false)]
    public Customer ParentCustomer { get; set; }

    public bool IsGoodCustomer
    {
      get
      {
        return this.CustomerType == CustomerTypes.Internal || this.CustomerType == CustomerTypes.External;
      }
    }

  }


* This source code was highlighted with Source Code Highlighter.

Monday, 15 June 2009

V2: WCF CollectionDataContract and DataMember attributes

Following Jeff's comment on the first version of this post, here are some explanations and a full class.

Q1. Why did I write "implement IEnumerable" twice?
A1. My original intention was to derive my class from ICollection<T>. Thus I had to implement IEnumerable and IEnumerable<T>.

Q2. Why do I bother to implement IEnumerable at all if the class is not "decorated" as IEnumerable?
A2. ICollection<T> "derives" from IEnumerable<T> and IEnumerable, so we have to implement both of them when writing a class that implements ICollection<T>

Here is a complete class:

 [DataContract]
  public class EntityCollectionWorkaround<EntityType> : ICollection<EntityType>
  {
    #region Constructor
    public EntityCollectionWorkaround()
    {
      Entities = new List<EntityType>();
    }
    #endregion

    [DataMember]
    public int AdditionalProperty { get; set; }

    [DataMember]
    public List<EntityType> Entities { get; set; }

    #region ICollection<T> Members

    public void Add(EntityType item)
    {
      Entities.Add(item);
    }

    public void Clear()
    {
      this.Entities.Clear();
    }

    public bool Contains(EntityType item)
    {
      return Entities.Contains(item);
    }

    public void CopyTo(EntityType[] array, int arrayIndex)
    {
      this.Entities.CopyTo(array, arrayIndex);
    }

    public int Count
    {
      get
      {
        return this.Entities.Count;
      }
    }

    public bool IsReadOnly
    {
      get
      {
        return false;
      }
    }

    public bool Remove(EntityType item)
    {
      return this.Entities.Remove(item);
    }

    public EntityType this[int index]
    {
      get
      {
        return this.Entities[index];
      }
      set
      {
        this.Entities[index] = value;
      }
    }
    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<EntityType> GetEnumerator()
    {
      return this.Entities.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
      return this.Entities.GetEnumerator();
    }

    #endregion
  }


* This source code was highlighted with Source Code Highlighter.

Thursday, 16 April 2009

WCF CollectionDataContract and DataMember attributes

I came to write this post just occasionally: I was required to add a property to an existing collection. The colleciton was generated on the WCF and was sent to a client. I was surprised to discover, that it's not supported and other people already faced this issue and expressed their frustration and posted different workarounds on the web. Unfortunately, none of these suggestions worked. So I decided to post a tested solution.

So here is the situation, we have an Entity class and a collection of them:
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.Collections.Generic;

[DataContract]
public class Entity
{
public int ID {get; set;}
public int Name {get; set;}
}

[CollectionDataContract]
public class EntityCollectionNotSupported : Collection
{
[DataMember]
public int AdditionalProperty { get; set; }
}


* This source code was highlighted with Source Code Highlighter.


It will compile, but will not serialize AdditionalProperty at all! So what can we do about it if EntitiesCollection must stay a Collection?

We can mark our collection as DataContract and wrap another collection inside. Like this:

[DataContract]
public class EntityCollectionWorkaround : ICollection
{
public EntityCollectionWorkaround()
{
Entities = new List();
}

[DataMember]
public int AdditionalProperty { get; set; }

[DataMember]
public List Entities { get; set; }

// Implement here ICollection,
// IEnumerable and IEnumerable members
// by wrapping Entities
}


* This source code was highlighted with Source Code Highlighter.


Hope it helped somebody