开发者

Best work around to fix DateTimeOffset over WCF Data Service issue

I try to create a WCF Data Service for an Entity Framework model, which contains some attributes of type DateTimeOffeset. However the WCF Data Service does not support the type DateTimeOffset as I f开发者_开发问答ound out after googling the exception text "The property 'CreationTime' on type 'Task' is of type 'DateTimeOffset' which is not a supported primitive type.'. See server logs for more details. The exception stack trace is: ...".

I'm now considering different approaches to solve this problem including:

  1. change the type to something that can be mapped to DateTime in the database (worst solution)

  2. Leave the column type in the database as DateTimeOffset, Map the column to two attributes in the Entity Framework model, one DateTime and an additional "Offset" attribute of type integer.

I really don't like any of these approaches. Has anyone found a good work around to fix this issue?


Just add the DateTimeOffset type as a KnownType to the EF data contract that contains the CreationTime property, like explained in http://msdn.microsoft.com/en-us/library/ms730167.aspx.

DateTimeOffset is one of the complex .NET types that is actually being handled as a primitive, except for that it is not registered by default as a KnownType to the serializers. So you need to do this manually.

Your code could look like this:

[DataContract]
[KnownType(typeof(DateTimeOffset))]
public class Task
{
    [DataMember]
    private DateTimeOffset CreationTime;
...


It's a bit of a hack using reflection, but putting the following in the application start up (I used WebActivator) has so far worked for me using October 2011 CTP.

var primitiveResourceTypeMapType = typeof(ResourceType).Assembly.GetType("System.Data.Services.Providers.PrimitiveResourceTypeMap");
Debug.Assert(primitiveResourceTypeMapType != null);
var builtInTypesMappingField = primitiveResourceTypeMapType.GetField("builtInTypesMapping", BindingFlags.NonPublic | BindingFlags.Static);
Debug.Assert(builtInTypesMappingField != null);

var existingMap = ((KeyValuePair<Type, string>[])builtInTypesMappingField.GetValue(null)).ToList();
existingMap.Add(new KeyValuePair<Type, string>(typeof(DateTimeOffset), "Edm.DateTimeOffset"));
existingMap.Add(new KeyValuePair<Type, string>(typeof(DateTimeOffset?), "Edm.DateTimeOffset"));
builtInTypesMappingField.SetValue(null, existingMap.ToArray());


I suggest passing a field from your service that contains TimeZone.GetUtcOffset Method return and then calculating the difference between that and the client's offset and then adding/subtracting that difference from the DateTime returned.


The problem you are seeing is because the XmlSerializer cannot serialize DataTimeOffset. However, if you use the DataContractSerializer, it will handle DateTimeOffset just fine. No need for custom serializers or extra hoops to jump through.

That's what I did and am having no issues.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜