1

I'm trying to return from MVC 4 web api ApiController objects generated from entity framework 4 edmx, with accept:json/application.

The problem is json formatter returns also the Navigation Properties, which I don't want to return (I want to return only the Primitive Properties).

So I've looked in the entity framework 4 code generated, in the Navigation Properties, and there are only XmlIgnoreAttribute and SoapIgnoreAttribute while I need JsonIgnoreAttribute.

I cannot change the code generated because it will be overwritten in the next change to the edmx, so how can I configure that the model generation will be produced with JsonIgnoreAttribute?

Thank you

2 Answers 2

3

While I don't know if this is a bug or unsupported feature I would recommend you to define view models and have your API controller actions return view models instead of your EF autogenerated domain models. The view models will obviously contain only the properties that you want to expose. A single view model could represent the aggregation of multiple domain models. So don't rely on any XmlIgnore, SoapIgnore, JsonIgnore, ... attributes. Rely on your view models.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes! Entities are not really suitable for serialization and other kinds of transport.
2

Ok, I found out what to do. We need to use custom DefaultContractResolver in this way:

public class ExcludeEntityKeyContractResolver : DefaultContractResolver
{
    private static Type mCollectionType = typeof(System.Data.Objects.DataClasses.RelatedEnd);

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var members = GetSerializableMembers(type);

        IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
        IList<JsonProperty> serializeProperties = new List<JsonProperty>();

        for (int i = 0; i < properties.Count; i++)
        {
            var memberInfo = members.Find(p => p.Name == properties[i].PropertyName);
            if (!memberInfo.GetCustomAttributes(false).Any(a => a is SoapIgnoreAttribute) && properties[i].PropertyType != typeof(System.Data.EntityKey))
            {
                serializeProperties.Add(properties[i]);
            }
        }
        return serializeProperties;
    }
}

and in Global.asax:

        JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
        serializerSettings.ContractResolver = new ExcludeEntityKeyContractResolver();
        var jsonMediaTypeFormatter = new JsonMediaTypeFormatter();
        jsonMediaTypeFormatter.SerializerSettings = serializerSettings;
        GlobalConfiguration.Configuration.Formatters.Insert(0, jsonMediaTypeFormatter);

and don't worry about performance, as CreateProperties will only be called once for every type for the whole application duration :)

1 Comment

Exactly what I was looking for. Thanks for this solution. Painstakingly creating models for DTOs is a waste of time in most cases for my projects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.