Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Web-API not serializing readonly property

I migrated an API method from a standard MVC action to the new asp.net Web-API beta and suddenly a read only property is no longer serialized (both returning JSON). Is this expected behaviour?

Edit: Added code sample

I have both Newtonsoft.Json 4.0.8 and System.Json 4.0 referenced through nuget packages

        public IQueryable<Car> Gets()
        {
             return _carRepository.GetCars();
        }

        public class Car
        {
            public IEnumerable<Photo> Photos
            {
                get { return _photos; }
            }

            public string PreviewImageUrl // No longer serialized
            {
                get
                {
                     var mainImage = Photos.FirstOrDefault(o => o.IsMainPreview) Photos.FirstOrDefault();
                        return mainImage != null ? mainImage.Url : (string.Empty);
                    }
                }
             }
         }
like image 855
terjetyl Avatar asked Feb 21 '12 16:02

terjetyl


2 Answers

The JsonMediaTypeFormatter that ships with the Beta uses a serializer that does not support read-only properties (since they would not round-trip correctly). We are planning on addressing this for the next realese.

In the mean-time you could use a custom JSON MediaTypeFormatter implementation that uses Json.NET (there's one available here) instead of the built-in formatter.

Update: Also check out Henrik's blog about hooking up a JSON.NET formatter: http://blogs.msdn.com/b/henrikn/archive/2012/02/18/using-json-net-with-asp-net-web-api.aspx

like image 137
marcind Avatar answered Nov 16 '22 04:11

marcind


I don't know if this is an expected behavior or not. I would say that this is expected for input parameters (because you cannot set their values) but not for output parameters. So I would say this is a bug for an output parameter. And here's an example illustrating the issue:

Model:

public class Product
{
    public Product()
    {
        Prop1 = "prop1 value";
        Prop2 = "prop2 value";
        Prop3 = "prop3 value";
    }

    public string Prop1 { get; set; }

    [ReadOnly(true)]
    public string Prop2 { get; set; }

    public string Prop3 { get; protected set; }
}

Controller:

public class ProductsController : ApiController
{
    public Product Get(int id)
    {
        return new Product();
    }
}

Request:

api/products/5

Result:

{"Prop1":"prop1 value","Prop2":"prop2 value"}

So if the property doesn't have a public setter it is not serialized which doesn't seem normal as the Product class is used as output in this case.

I would suggest opening a connect ticket so that Microsoft can fix this before the release or at least tell that this is by design.

like image 41
Darin Dimitrov Avatar answered Nov 16 '22 04:11

Darin Dimitrov