问题
As most of the people I've also ran into a problem of circular reference error when serializing (terrible) EF objects to JSON. Doing db.Detach(efObject) helps - but I still get garbage like "EntityKey" outputted.
So I was wondering if there is an option (through JsConfig?) to tell serializer to ignore Properties either through name (EntityKey) or through type (EntityReference<T> or EntityCollection<T>)?
Or will I be forced to ditch EF alltogether and switch to something better (I do not want to manually define ORM classes - I want them automatically generated from DB)?
回答1:
You shouldn't try to re-use Entity Framework types as DTO's since they are by design poor substitutes for DTOs. You should instead map them to special purpose DTO types using ServiceStack's built-in TranslateTo/PopulateFrom mappers (or AutoMapper) and return those.
With that said, use IgnoreDataMember or specify DataMembers on properties you want serialized.
回答2:
DISCLAIMER: I am currently doing prototyping and for me convenience matters more than robustness of solution. So, what I've done is not a good way to go - I am copy-pasting it here just in case somebody else is in same position and wants an easy (not the best) way out. You've been warned.
I presume you are already using ServiceStack.Text in your MVC project. If that's not the case, follow instructions from this QA: ASP.NET MVC Json DateTime Serialization conversion to UTC
Check out ServiceStack.Text library from GitHub and (of course) reference it in your MVC project instead of DLL.
Add this to ServiceStack.Text/JsConfig class:
// Added properties for global excluding public static Type[] GlobalExcludedBaseTypes; public static string[] GlobalExcludedProperties;
Change static TypeConfig() in ServiceStack.Text/TypeConfig class:
static TypeConfig() { config = new TypeConfig(typeof(T)); var excludedProperties = JsConfig<T>.ExcludePropertyNames ?? new string[0]; var excludedGlobalBaseTypes = JsConfig.GlobalExcludedBaseTypes ?? new Type[0]; var excludedGlobalProperties = JsConfig.GlobalExcludedProperties ?? new string[0]; IEnumerable<PropertyInfo> properties = null; if (excludedProperties.Any() || excludedGlobalBaseTypes.Any() || excludedGlobalProperties.Any()) { properties = config.Type.GetSerializableProperties(). Where(x => !excludedProperties.Contains(x.Name) && !excludedGlobalProperties.Contains(x.Name) && !excludedGlobalBaseTypes.Contains(x.PropertyType.BaseType)); } else { properties = config.Type.GetSerializableProperties(); } Properties = properties.Where(x => x.GetIndexParameters().Length == 0).ToArray(); Fields = config.Type.GetSerializableFields().ToArray(); }
In your Global.asax just add these two lines:
JsConfig.GlobalExcludedProperties = new[] { "EntityKey", "EntityState" }; JsConfig.GlobalExcludedBaseTypes = new[] { typeof(RelatedEnd), typeof(EntityReference) };
That's it - EntityState & EntityKey will no longer be serialized and you'll no longer need to worry about circular dependencies.
But, again - THIS IS NOT BEST PRACTICE - and as soon as you stabilize your solution be sure to follow what mythz recommended and migrate toward DTO's.
回答3:
You can use ScriptIgnore attribute on your model:
public class Item
{
[ScriptIgnore]
public Item ParentItem { get; set; }
}
来源:https://stackoverflow.com/questions/14998890/do-not-serialize-entity-framework-class-references-in-json-servicestack-text-li