Reputation: 74
I'm trying to enforce a use of an IsoDateTimeConverter on a specific property.
I register the routes and the Content Negotiator:
public class RouteMapper : IServiceRouteMapper
{
public void RegisterRoutes(IMapRoute mapRouteManager)
{
mapRouteManager.MapHttpRoute("SbApi", "default", "{controller}/{action}", new[] { "SbApi.Controllers" });
GlobalConfiguration.Configuration.Services.Replace(typeof(System.Net.Http.Formatting.IContentNegotiator), new JsonContentNegotiator());
}
}
public class JsonContentNegotiator : IContentNegotiator
{
public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
{
var formatter = new JsonMediaTypeFormatter();
formatter.UseDataContractJsonSerializer = false;
var isoDateConverter = formatter.SerializerSettings.Converters
.OfType<IsoDateTimeConverter>()
.FirstOrDefault();
if(isoDateConverter!=null){
formatter.SerializerSettings.Converters.Remove(isoDateConverter);
}
formatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = "dd-MM-yyyy" }); // custom date format, to see if the converter is used
var result = new ContentNegotiationResult(formatter, new MediaTypeHeaderValue("application/json"));
return result;
}
}
Attribute used on the property:
[JsonConverter(typeof(IsoDateTimeConverter))]
public System.DateTime EndDate { get; set; }
The output of the serializer:
"EndDate":"2016-01-01T00:00:00"
How do I make it use the IsoDateTimeConverter?
Edit:
I used a custom IContentNetogiator to enforce use of JSON over XML.
I used the custom datetime format just to see if the converted gets actually used.
What I really need is an ISO format (with the full timezone) but I'm not able to enforce it for some reason. I tried setting it up in the CustomDate, but to no avail.
public CustomDatetimeConverter()
{
base.DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; // none of these work..
base.DateTimeFormat = "o";
base.Culture = System.Globalization.CultureInfo.InvariantCulture;
base.DateTimeStyles = System.Globalization.DateTimeStyles.AssumeLocal;
}
Edit 2: Anyway, I got it working, sort of. Since nothing was working and I don't need the millisecond part of the time, I ended using the following format: "yyyy'-'MM'-'dd'T'HH':'mm':'ss.000000zzz" . The "zzz" is used in place of "K" which for some reason doesn't work.
Upvotes: 1
Views: 800
Reputation: 129697
There are a couple of ways to solve this. Neither involves replacing the IContentNegotiator
. The first (and easiest) way is to create a subclass of the IsoDateTimeConverter
having your custom date format:
class CustomDateTimeConverter : IsoDateTimeConverter
{
public CustomDateTimeConverter()
{
base.DateTimeFormat = "dd-MM-yyyy";
}
}
Then change the [JsonConverter]
attribute on your EndDate
property:
[JsonConverter(typeof(CustomDateTimeConverter))]
public System.DateTime EndDate { get; set; }
Another way to do the same thing is to create a custom IContractResolver
that will apply the IsoDateTimeConverter
to your target property programmatically. Below is the code you would need for the resolver. Replace Your_Class
with the name of the class containing the EndDate
property.
class CustomResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type,
Newtonsoft.Json.MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
if (type == typeof(Your_Class))
{
JsonProperty prop =
props.Where(p => p.PropertyName == "EndDate")
.FirstOrDefault();
if (prop != null)
{
prop.Converter =
new IsoDateTimeConverter { DateTimeFormat = "dd-MM-yyyy" };
}
}
return props;
}
}
To install this resolver in your project, add the following line to the Register
method of your WebApiConfig
class:
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
new CustomResolver();
Upvotes: 2