Update
Now that you have included your service contract in the question, I see there is a more fundamental problem. WCF is for exchanging Data Contract objects, and is format-agnostic between XML and JSON. It's so agnostic that there's no straightforward way to access the underlying raw request or response streams. Instead WCF insists on doing the binding for you. Since your uploaded JSON is not a JSON primitive, trying to bind it to string message
fails.
Instead, you need to define your service along the lines of
[ServiceContract]
public interface IService
{
[OperationContract]
[FaultContract( typeof( MessageUnAuthenticatedFault ))]
[WebInvoke( Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Process" )]
ResponseClass Process( TestClass message );
}
Where ResponseClass
is whatever you want to return. Take a look at WCF rest service to get post JSON data and retrieve JSON data with DataContract for an example.
If you really need the underlying post stream to do manual parsing, you might try the techniques from WCF REST Service JSON Post data and WCF + REST: Where is the request data?.
Original Answer
WCF does not use Json.NET for JSON serialization. It uses DataContractJsonSerializer
. Thus annotating your types with [JsonProperty]
will have no effect. Instead, you need to set DataMemberAttribute.Name
, i.e.:
[DataContract]
public class TestClass
{
[DataMember]
public long Id { get; set; }
[DataMember(Name = "request_name")]
public string RequestedName { get; set; }
[DataMember(Name = "request_type")]
public string RequestType { get; set; }
[DataMember(Name = "request_key")]
public string RequestKey { get; set; }
[DataMember(Name = "descriptive_name")]
public string DescriptiveName { get; set; }
[DataMember(Name = "owner_internal_id")]
public string OwnerInternalId { get; set; }
[DataMember]
public string URL { get; set; }
[DataMember]
public Status Status { get; set; }
[DataMember]
public DateTime? Created { get; set; }
[DataMember]
public DateTime? Modified { get; set; }
}
To test standalone JSON deserialization using this serializer, you may use the following helper methods:
public static partial class DataContractJsonSerializerHelper
{
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
public static string SerializeJson<T>(T obj, DataContractJsonSerializer serializer = null)
{
serializer = serializer ?? new DataContractJsonSerializer(obj.GetType());
using (var memory = new MemoryStream())
{
serializer.WriteObject(memory, obj);
memory.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memory))
{
return reader.ReadToEnd();
}
}
}
public static T DeserializeJson<T>(string json, DataContractJsonSerializer serializer = null)
{
serializer = serializer ?? new DataContractJsonSerializer(typeof(T));
using (var stream = GenerateStreamFromString(json))
{
var obj = serializer.ReadObject(stream);
return (T)obj;
}
}
}
And then do:
var test = DataContractJsonSerializerHelper.DeserializeJson<TestClass>(jsonString);
You must also format DateTime
properties in Microsoft's preferred "/Date(1329159196126-0500)/"
format, or use a surrogate for deserialization to do manual parsing. See DataContractJsonSerializer - Deserializing DateTime within List and WCF Extensibility – Serialization Surrogates for details, and ASP.NET AJAX: Inside JSON date and time string for background. Or just use a surrogate property for each DateTime
, e.g.:
[IgnoreDataMember]
public DateTime? Created { get; set; }
[DataMember(Name = "Created")]
string CreatedString
{
get
{
if (Created == null)
return null;
// From https://stackoverflow.com/questions/114983/given-a-datetime-object-how-do-i-get-a-iso-8601-date-in-string-format
return Created.Value.ToString("s", System.Globalization.CultureInfo.InvariantCulture);
}
set
{
if (string.IsNullOrEmpty(value))
Created = null;
else
Created = DateTime.Parse(value);
}
}
[DataMember]
public DateTime? Modified { get; set; }
}
If you really want to use Json.NET with WCF for deserialization, you will need to do some work. See C# WCF REST - How do you use JSON.Net serializer instead of the default DataContractSerializer? and, possibly, Using Custom WCF Body Deserialization without changing URI Template Deserialization.
For a rundown of JSON serializers used by various Microsoft frameworks see Json serializers in ASP.NET and other.