I know there are several posts over the years on this: Sorry they wont let me add this many links ??
to link a few..but none of these are complete and citing the full scope of technologies needed...typically referencing a class that is ellusive to find...With that I will post what I have and the bottom line is while the formatter DO get into the formatters collection the custom formatter is not called. Now it could be that I am using the complete wrong solution but no solution seems clear...and this should be easy to accomplish. I have tried every content-type possible as well as the following:
Model:
public class TEST_Hotel : IHotelOption
{
public int AlternateCount{get;set;}
public float AverageBaseRate{get;set;}
public List<string> policyViolations{get;set;}
public int TravelerBookings{get;set;}
[JsonProperty("hotelId")]
public string VendorHotelID{get;set;}
}
Adding the [DataContract] [DataMember] attributes of course will work as it will use the DataContract serializer and NOT the custom serializer. Note: that the JsonProperty is NOT recognized since the custom json.net formatter is not used.
Service:
[OperationContract]
[Description("Retrieves a list of hotel objects based on search parameters")]
[WebGet(
BodyStyle = WebMessageBodyStyle.WrappedRequest,
// ResponseFormat = WebMessageFormat.Json,
// RequestFormat = WebMessageFormat.Json,
UriTemplate = "GetHotels?queryparams={parameters}")]
public HotelResults GetHotels(string parameters)
{
return worker.GetHotels(parameters);
}
Global:
using System;
using System.ServiceModel.Activation;
using System.Web.Routing;
using System.Web;
using System.Linq;
using System.Web.Http;
namespace HotelService
{
public class Global : System.Web.HttpApplication
{
private void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(Hotels)));
GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonNetMediaTypeFormatter() );
}
}
}
JsonNetMediaTypeFormatter:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
namespace HotelService
{
public sealed class JsonNetMediaTypeFormatter : JsonMediaTypeFormatter
{
public JsonSerializer Serializer
{
get;
private set;
}
public JsonNetMediaTypeFormatter(JsonSerializer serializer = null)
{
Collection<MediaTypeHeaderValue> supportedMediaTypes = base.SupportedMediaTypes;
MediaTypeHeaderValue mediaTypeHeaderValue = new MediaTypeHeaderValue("application/json");
mediaTypeHeaderValue.CharSet = "UTF-8";
supportedMediaTypes.Add(mediaTypeHeaderValue);
Collection<MediaTypeHeaderValue> mediaTypeHeaderValues = base.SupportedMediaTypes;
MediaTypeHeaderValue mediaTypeHeaderValue1 = new MediaTypeHeaderValue("text/json");
mediaTypeHeaderValue1.CharSet = "UTF-8";
mediaTypeHeaderValues.Add(mediaTypeHeaderValue1);
this.Serializer = (serializer != null ? serializer : new JsonSerializer());
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
return readStream.ReadAsJson(type, this.Serializer);
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
return writeStream.WriteAsJson(value, this.Serializer);
}
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
return true;
}
}
internal static class StreamExtensions
{
internal static Task<object> ReadAsJson(this Stream stream, Type instanceType, JsonSerializer serializer)
{
if (stream == null)
{
return null;
}
return Task<object>.Factory.StartNew(() =>
{
object obj1;
using (JsonTextReader reader = new JsonTextReader(new StreamReader(stream)))
{
object obj = serializer.Deserialize(reader);
obj1 = (obj.GetType().IsSubclassOf(instanceType) ? obj : serializer.Deserialize(reader, instanceType));
}
return obj1;
});
}
internal static Task WriteAsJson(this Stream stream, object instance, JsonSerializer serializer)
{
if (instance == null)
{
return null;
}
return Task.Factory.StartNew(() =>
{
using (JsonTextWriter writer = new JsonTextWriter(new StreamWriter(stream)))
{
serializer.Serialize(writer, instance);
writer.Flush();
}
});
}
}
}
packages:
<packages>
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net451" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net451" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net451" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net451" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net451" />
</packages>
What happens is if I remove the Service ResponseFormat then xml is returned if i put it back json is returned but the custom formatter is not used. Breaking in global i can see the custom formatter at the 0 index of the collection.It would appear a mapper or some binding is missing.