Web Api won't serialize my Object Graph - json

I got two simple entities:
public class Ingredient : IEntity
{
public Ingredient()
{
Drinks = new List<Drink>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Drink> Drinks { get; set; }
}
public class Drink : IEntity
{
public Drink()
{
Ingridients = new List<Ingredient>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Ingredient> Ingridients { get; set; }
public string Approach { get; set; }
}
I get the following error:
Object graph for type 'Gudo.Core.Model.Ingredient' contains cycles and cannot be serialized if reference tracking is disabled.
I've tried using the JsonIgnore Attribute on the Drinks collection and I've tried using:
JsonSerializerSettings jsSettings = new JsonSerializerSettings();
jsSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
In my global.asax
Nothing works..
Please help.

Did you make sure to set this on the JSON formatter's serializer settings? This line should do it for you:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

Related

Dotnet Core DB Scaffold creates additional Collections for Object

I have a Mysql Database and want to create a scaffold to try a data-first .net project. I got the scaffold to work, which was great, but it is creating these false Collections on my model objects for related tables.
For my coin object below, I only have the 5 fields on the top, but it is creating the collections to any of the tables where Coin is a foreign key. This is not really making any sense to me. I will never populate this data and cannot see any settings to stop this from happening.
public partial class Coin
{
public Coin()
{
LedgerTransactions = new HashSet<LedgerTransactions>();
Price = new HashSet<Price>();
TradeFeeCoin = new HashSet<Trade>();
TradeForCoin = new HashSet<Trade>();
TradeTradeCoin = new HashSet<Trade>();
}
[Column(TypeName = "int(11)")]
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(5)]
public string Symbol { get; set; }
public byte? SortOrd { get; set; }
[Column(TypeName = "bit(1)")]
public bool? IsBaseCurrency { get; set; }
[InverseProperty("Coin")]
public ICollection<LedgerTransactions> LedgerTransactions { get; set; }
[InverseProperty("Coin")]
public ICollection<Price> Price { get; set; }
[InverseProperty("FeeCoin")]
public ICollection<Trade> TradeFeeCoin { get; set; }
[InverseProperty("ForCoin")]
public ICollection<Trade> TradeForCoin { get; set; }
[InverseProperty("TradeCoin")]
public ICollection<Trade> TradeTradeCoin { get; set; }
}
I created this table from a Code-First approach, and that model only had the 5 fields in it that I would expect. Am I doing something wrong?

Breezejs entity save failing because json data is too large

Breeze seems to be creating a very large file considering the object model I am passing it to save.
I am only saving one instance of a drug with 1 Drug option with 1 available route and some text fields with a single word in each.
When I grab the bundle from debug.breeze.js from line 14705 and save it to a text file the file is 35+ mb. This seems like an aweful lot of data for this straight forward object model.
Is there any way to slim down the json with just the objects? So I don't have to alter the IIS settings?
****************** Link to exported json that breeze is sending to the server ***********
Sample of json that's causing the problem
****************Here is a screen shot of the graph *************
my datacontext.saveChanges code......
function saveDictionaryChanges(entity) {
var graph = manager.getEntityGraph(entity, 'drugIndications, ' +
'drugOptions, ' +
'drugOptions.concentrations, ' +
'drugOptions.availableRoutes, ' +
'drugOptions.availableDrugForms, ' +
'drugOptions.availableUnits');
// Filter for changes only
graph = graph.filter(function (entity) {
return entity.entityAspect.entityState.isAddedModifiedOrDeleted();
});
return manager.saveChanges(graph)
.then(saveSucceeded, saveFailed);
function saveSucceeded(result) {
//TODO: Commented out because WIP is on the back burner
//zStorage.save();
logSuccess('Saved Data', result, true);
}
function saveFailed(error) {
var msg = config.appErrorPrefix + 'Save failed: ' +
breeze.saveErrorMessageService.getErrorMessage(error);
error.message = msg;
logError(msg, error);
throw error;
}
}
my object model is
There are 4 other inherited available route types liquid,inhalation,injectable and topical. I only included AvailableSolidRoutes to help shorten he question.
public class AvailableRoute {
public int Id { get; set; }
public int DrugOptionId { get; set; }
public int RouteId { get; set; }
public virtual Route Route { get; set; }
}
public class AvailableSolidRoute : AvailableRoute {
public AvailableSolidRoute( ) { }
}
There is also a Inhalation,Injectable & topical concentration object that inherit from concentration. I've only include LiquidConcentration to help shorten the question.
public abstract class Concentration {
public int Id { get; set; }
public int DrugOptionId { get; set; }
public DrugOption DrugOption { get; set; }
public decimal Measure{ get; set; }
public int MassUnitId { get; set; }
public virtual Unit MassUnit { get; set; }
public int VolumeUnitId { get; set; }
public virtual Unit VolumeUnit { get; set; }
public int? DrugFormId { get; set; }
public virtual DrugForm DrugForm { get; set; }
public int DisplayOrder { get; set; }
}
public class LiquidConcentration : Concentration {
public LiquidConcentration( ) {}
}
There 4 other inherited types like solid option Liquid,Inhalation,Injectable & Topical
public class DrugOption {
public int Id { get; set; }
public int DrugId { get; set; }
public Drug Drug { get; set; }
public List<AvailableDrugForm> AvailableDrugForms { get; set; }
public List<AvailableRoute> AvailableRoutes{ get; set; }
public List<AvailableUnit> AvailableUnits { get; set; }
public List<Concentration> Concentrations { get; set; }
public string SpecialInstructions { get; set; }
}
public class SolidOption : DrugOption {
public SolidOption( ) { }
}
Drug is the root class that all the previous classes relate to:
public class Drug {
public int Id { get; set; }
public string Name { get; set; }
public string Alias{ get; set; }
public string Directions { get; set; }
public bool DirectionsIsEditable { get; set; }
public string SpecialDirections { get; set; }
public bool SpecialDirectionsIsEditable { get; set; }
public int? DisplayOrder { get; set; }
public IList<DrugIndication> DrugIndications { get; set; }
public IList<DrugOption> DrugOptions { get; set; }
public Drug( ) { }
}
***************** I fixed this issue (Was self induced hehe!) *************
So in order to make it easier to bind my "DrugOptions" to the UI. I created
clientside properties on the drug for each type of drug options.
I did not understand what this code was actually doing.. I added it thinking it would
remove the clientside property before sending entity changes to breeze. That is not it's purpose.
Rightly so breeze was confused about the clientside properties because it does not know about them.
if (changedProp === 'solidOption') {
delete changeArgs.entity.entityAspect.originalValues[changedProp];
}
I moved these properties to the Controller and it's perfectly fine now :)

How to add to a collection in Entity Framework 4.1

I'm trying to add an object to an IList entity but the runtime throws a 'Object reference not set to an instance of an object.' exception.
Here is my model:
public class Discussion
{
[Key]
public int DiscussionId { get; set; }
public string Title { get; set; }
public virtual List<Message> Messages { get; set; }
public virtual List<Tag> Tags { get; set; }
public Guid Guid { get; set; }
public string UrlTitle { get; set; }
}
and here is the problematic line:
newDiscussion.Messages.Add(newMessage);
Apparently newDiscussion.Messages is null. What am I doing wrong?
Mark
You should initialize any collections inside of the class's constructor.
public class Discussion
{
public Discussion()
{
Messages = new List<Message>();
Tags = new List<Tag>();
}
// ...
}

Self referencing loop detected serialization exception

This is my class:
public partial class Event
{
public Event()
{
this.Comments = new HashSet<Comment>();
this.Rates = new HashSet<Rate>();
this.RawDates = new HashSet<RawDate>();
}
public int ID { get; set; }
public string Title { get; set; }
public string Summary { get; set; }
public string SiteURL { get; set; }
public string ContactEmail { get; set; }
public string LogoURL { get; set; }
public int EventType_ID { get; set; }
public Nullable<int> Location_ID { get; set; }
public Nullable<System.DateTime> BegginingDate { get; set; }
public string nTrain { get; set; }
public string Content { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual Conference Conference { get; set; }
public virtual ICollection<Rate> Rates { get; set; }
public virtual ICollection<RawDate> RawDates { get; set; }
public virtual EventType EventType { get; set; }
public virtual Location Location { get; set; }
}
When I call web api post method, exception mentioned in the title is thrown in this line:
var response = await client.PostAsJsonAsync("api/event", event);
I added [JsonIgnore] above every virtual field in Event class. This time serialization worked, but ignored fields were not serialized, their value is null. I really need all information contained in Event object. How can I solve this problem?
Adding below configuration in WebAPIConfig.cs resolves the bug.
var json = config.Formatters.JsonFormatter;
//Below configuration to mandatory to resolve the Self referencing loop detected with
"Newtonsoft.Json.JsonSerializationException" ,
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
Circular referencing objects cannot be JSON serialized. I would recommend you using a view model in which you will include the properties you need and then have your action return this view model instead of the actual domain model.

Code First Object not properly instantiating

I have a class department inheriting from activeentity
public class ActiveEntity : Entity, IActive
{
public ActiveEntity()
{
IsActive = true;
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid Id { get; set; }
public bool IsActive { get; set; }
[Timestamp, ScaffoldColumn(false), DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Computed)]
public Byte[] Timestamp { get; set; }
[ScaffoldColumn(false)]
public string CreationUserId { get; set; }
[ScaffoldColumn(false)]
public string LastModifiedUserId { get; set; }
}
public class Department:ActiveEntity
{
public Department()
{
this.Address = new DepartmentAddress();
}
[StringLength(9),MinLength(9),MaxLength(9)]
public string Name { get; set; }
public Guid ManagerId { get; set; }
[UIHint("AjaxDropdown")]
public User Manager { get; set; }
public Guid? AddressId { get; set; }
public DepartmentAddress Address { get; set; }
public ICollection<OverheadRate> OverheadRates { get; set; }
}
I am just using annotations no Fluent API. The data saves to the data Sql Server 2008 just fine however the address object never gets instantiated, even though I have the context use the include
return c.Set<Department>().Include(d => d.Address).Include(d => d.Manager).Where(predicate);
The data is returned I run sql profiler and then run the query it returns the correct data.
Any thoughts or suggestions?
Remove instantiating the address (this.Address = new DepartmentAddress();) in the Department constructor. Instantiating navigation references in the default constructor is evil and has nasty side effects like these:
What would cause the Entity Framework to save an unloaded (but lazy loadable) reference over existing data?
EF 4.1 Code First: Why is EF not setting this navigation property?