BlueSky
BlueSky

Reputation: 1539

WCF Service Reference for DateTimeOffset? not using FCL type

I am using .NET 4.5.1 for my WCF service, and .NET 4.0 for a client windows service application.

In the Data Contract, there is a DataMember of type DateTimeOffset? (a nullable DataTimeOffset).

When I Add Service Reference to the WCF service, it thinks that DateTimeOffset? is a complex type. In other words, it doesn't think it's a System.DateTimeOffset?, it thinks it's a ServiceReference1.DateTimeOffset?

How do I fix this?

Here's what I've tried so far:

  1. Create the most simple example solution that demonstrates this. Unfortunately I couldn't recreate the issue, so it must be something unique to my configuration.

  2. Annotate the DataContract class with [KnownType(typeof(DateTimeOffset?))]. Unfortunately this didn't do anything.

  3. Check "Reuse types in referenced assemblies". This had the effect of the "ServiceReference1" object not being available at all in the Console Application.

Anyone have any other ideas on how to fix this?

Thank you.

Upvotes: 12

Views: 965

Answers (3)

Lionia Vasilev
Lionia Vasilev

Reputation: 12757

That can happens when either your data contracts projects is not properly builded or you not select to reuse library that contain DateTimeOffset and Nullable<> - mscorlib and/or your data contract project.

So make sure that:

  1. Data contracts project target framework is not greater than .NET Framework 4.0. Because .NET Framework is not forward compatable. Reference to it from client project must not be marked with warning sign:
    Broken reference in client library
  2. Data contracts project is builded
  3. Both mscorlib and your data contracts project are in the reference list which types need to be reused or you choose to reuse type in all referenced assemblies: Service reference configuration dialog window

Upvotes: 1

Dan Ling
Dan Ling

Reputation: 2984

You're on the right track with KnownType.

In order to achieve your goal, you cannot use "Add Service Reference". Instead, your client application must have a reference to your [ServiceContract] class. Then, you can directly invoke the service using a ChannelFactory.

Server Code:

using System;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace Server
{
    public class Service : IService
    {
        public ReturnContract GetOffset()
        {
            return new ReturnContract { Offset = new DateTimeOffset(DateTime.Now) };
        }
    }

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        ReturnContract GetOffset();
    }

    [DataContract]
    [KnownType(typeof(DateTimeOffset))]
    public class ReturnContract
    {
        [DataMember]
        public DateTimeOffset? Offset { get; set; }
    }
}

Client Code

using Server;
using System;
using System.ServiceModel;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            var cf = new ChannelFactory<Server.IService>("endpoint");
            var service = cf.CreateChannel();
            ReturnContract c = service.GetOffset();

            Console.WriteLine(c.Offset);
            Console.ReadLine();
        }
    }
}

Upvotes: 1

dblood
dblood

Reputation: 1778

You're definitely going to have to specify "Reuse types in referenced assemblies" to get the behavior you are looking for.

The question then becomes, what is causing your service to not be available in your Console application. I would guess that your solution is not quite setup correctly, but I would need more details. A screen shot of the solution containing the console application would be ideal.

Did you add your service reference to the Console App project or a different project?

Upvotes: 0

Related Questions