Phoenix_uy
Phoenix_uy

Reputation: 3294

Problem with DataContract and hierarchy on WCF

i have a problem with an object in my wcf project. I have lets say this object:

[DataContract(Name="ClassA")]
public class Person{
   //---attributes---
}

[DataContract(Name="ClassB")]
public class Men : Person{
  //---attributes---
}

Where ClassB is child of ClassA on the other side. Then i have a method that is post:

[OperationContract]
[WebInvoke(UriTemplate= "Person", ResponseFormat = WebMessageFormat.Json, Method= "POST")]
public string PostPerson(Person person) {
    if(person is Men){
       //code...
    }
}

The thing is that i receive the person (in the other side, they sendme as a ClassB) but the person is Men returns false.. why?

Upvotes: 4

Views: 1044

Answers (2)

Jason Shantz
Jason Shantz

Reputation: 903

As Ryan Gross mentions, you need Men to be a known type. Here's a similar question/answer here on SO. One option not mentioned in the linked article is the KnownType attribute. Here's an example of code I've used in the past. The prerequisite is that this class is the base class for all of your data contracts and all of your data contracts are in the same assembly:

/// <summary>
///   Base class for all data contracts.
/// </summary>
[DataContract(Name = "Base", Namespace = "your namespace")]
[KnownType("GetKnownTypes")]
public class BaseDC : IExtensibleDataObject
{
  #region Constants and Fields

  /// <summary>
  ///   Instance used to control access to the known types list.
  /// </summary>
  private static readonly object _knownTypesLock = new object();

  /// <summary>
  ///   Classes derived from this class.  Needed to ensure proper functioning of the WCF data
  ///   constract serializer.
  /// </summary>
  private static List<Type> _knownTypes;

  #endregion

  #region Properties

  /// <summary>
  ///   Gets or sets an <c>ExtensionDataObject</c> that contains data that is not recognized as belonging to the
  ///   data contract.
  /// </summary>
  public ExtensionDataObject ExtensionData { get; set; }

  #endregion

  #region Public Methods

  /// <summary>
  ///   Enumerates the types in the assembly containing <c>BaseDC</c> that derive from <c>BaseDC</c>.
  /// </summary>
  /// <returns>List of <c>BaseDC</c>-derived types.</returns>
  [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
    Justification = "Not appropriate for a property.")]
  public static IEnumerable<Type> GetKnownTypes()
  {
    lock (_knownTypesLock)
    {
      if (_knownTypes == null)
      {
        _knownTypes = new List<Type>();
        Assembly contractsAssembly = Assembly.GetAssembly(typeof(BaseDC));
        Type[] assemblyTypes = contractsAssembly.GetTypes();
        foreach (Type assemblyType in assemblyTypes)
        {
          if (assemblyType.IsClass && !assemblyType.IsGenericType)
          {
            if (assemblyType.IsSubclassOf(typeof(BaseDC)))
            {
              _knownTypes.Add(assemblyType);
            }
          }
        }

        _knownTypes.Add(typeof(BaseDC));
      }

      return _knownTypes;
    }
  }

  #endregion
}

Upvotes: 0

Ryan Gross
Ryan Gross

Reputation: 6515

You need to add the [ServiceKnownType(typeof(Men))] attribute to the PostPerson method.

Upvotes: 1

Related Questions