Search code examples
c#jsonasp.net-web-api2odata

JSON Serialization of URI Type in WebAPI 2 ODATA 3 C# Project


I'm seeing C# URI types serialized to JSON in an ODATA 3 controller in my WebAPI 2 project as an array of segments that does not include the domain. I've tried everything I can think of to change this (including fiddling with the serialization settings and even trying out the contract serializer instead of JSON.Net). Nothing seems to change the behavior. Note, I am not using .Net Core. Here is a code sample, condensed into a single snippet.

namespace WebApplication1.Controllers
{
    public class MyObject
    {
        public Uri Url { get; set; }

        public string Name { get; set; }

        public string ID { get; set; }
    }

    public class MyObjectsController : ODataController
    {
        private static ODataValidationSettings _validationSettings = new ODataValidationSettings();

        public IHttpActionResult GetMyObjects(ODataQueryOptions<MyObject> queryOptions)
        {
            try
            {
                queryOptions.Validate(_validationSettings);

                return Ok<IEnumerable<MyObject>>(new List<MyObject>() { new MyObject() { ID="asdf", Name="123rwe", Url = new Uri("http://www.webapp.com/sites/page.html") } });
            }
            catch (ODataException ex)
            {
                return BadRequest(ex.Message);
            }
        }

    }
}

This generates the following JSON in the browser:

{
  "odata.metadata":"http://localhost:51607/odata/$metadata#MyObjects","value":[
    {
      "Url":{
        "Segments":[
          "/","sites/","page.html"
        ]
      },"Name":"123rwe","ID":"asdf"
    }
  ]
}

This is what I'd like (without changing the Url property to a string):

{
  "odata.metadata":"http://localhost:51607/odata/$metadata#MyObjects","value":[
    {
      "Url":"http://www.webapp.com/sites/page.html","Name":"123rwe","ID":"asdf"
    }
  ]
}

Any thoughts?

UPDATE: Further research is suggesting that serialization behavior for URI types in WebAPI ODATA is controlled by the odataentityreferencelink and odataentityreferencelinkserializer classes. Specifically, URI type appear to be converted to odataentityreferencelink types which are then serialized in the manner I posted above (as an array of segments not including the root domain). I still need to know how to change this behavior, however the documentation for these two classes is not proving helpful. Last, I've confirmed this problem is not specific to the JSON output format. The serialization behavior for both XML/Atom and JSON are identical: URIs are broken down into an array of segments.


Solution

  • MS Premier support provided a final answer to this which I'll share below.

    1. There is no option to directly JSON serialize an URI type, normally it would be broken into array of segments as you are observing in your code
    2. The domain name will be eliminated as a normal scenario
    3. The option you can go for is to create a custom URI Converter deriving from JSONConverter which is a part of Newtonsoft.Json namespace