Deserializing json issue - inherited linq2SQL object - c#

I have used Linq-to-SQL objects in my web app. My base and inherited classes look like this:
//Base Class: this will define the attributes that is auto-generated
//when using Linq-2-SQL ORM. Note this class is a partial class
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Categories")]
[global::System.Runtime.Serialization.DataContractAttribute()]
public partial class Category : INotifyPropertyChanging, INotifyPropertyChanged
//Inherited Class:
[Serializable]
public class CategoryEntity : Category
{
private int _ActiveAdsCount;
public int ActiveAdsCount
{
get
{
return _ActiveAdsCount;
}
set
{
_ActiveAdsCount = value;
}
}
public int DisplaySequence { get; set; }
}
when serialize, the Json OUTPUT is (note the ActiveAdsCount and DisplaySequence values):
[{"ActiveAdsCount":3429,"DisplaySequence":99,"CategoryID":636,"ParentCategoryID":635,"CategoryName":"propForRent","CategoryImageFN":null}]
When I am calling the deserialze object method
result = JsonConvert.DeserializeObject<T>(responseText);
where T is List
Result: it shows "ActiveAdsCount" and "DisplaySequence" have 0 values while the json shows proper correct information coming from Database. So, the problem is in deserialization.
I am using 4.5.1 version of Newtonsoft.Json.dll of .Net 4.0 framework

Moreover, I have marked my CategoryEntity class with DataContract attribute and its members to Datamember for serialization purpose. I notice that the Serialization attribute is making only the instance as serializable but not its members. So, the new class look like this:
[DataContract]
public class CategoryEntity : Category
{
[DataMember]
public int ActiveAdsCount { get; set; }
[DataMember]
public int DisplaySequence { get; set; }
[DataMember]
public IList<CategoryEntity> SubCategories { get; set; }
[DataMember]
public IList<BasicCategoryInfo> SubCategoriesBasicInfoList { get; set; }
[DataMember]
public string ParentCategoryNameEn { get; set; }
[DataMember]
public int CityID { get; set; }
}
#JasonJong Thanks very much for your comment.

Related

ASMX can't set known type attributes

Im working on ASMX service that allows me to work with databases and their tables. The schema looks like this
[DataContract]
public class DataBase
{
[DataMember]
public string Name { get; set; }
[DataMember]
public List<Table> Tables { get; set; }
...
}
[DataContract]
public class Table
{
[DataMember]
public string Name { get; set; }
[DataMember]
public List<Column> Columns { get; set; }
[DataMember]
public List<List<object>> Data { get; set; }
...
}
[DataContract]
public class Column
{
[DataMember]
public string Name { get; set; }
[ DataMember]
public string Type { get; set; }
...
}
"Data" field is meant to keep a table of all values of different types. The problem is - i have to work with a few of custom types:
public class Email
{
[DataMember]
public string address { get; set; }
...
}
public class Strings : List<string>
{
public Strings(IEnumerable<string> collection) : base(collection) { }
...
}
And the problem is that web service does not create references to these types. I do not use them in methods explicitly, but store in table. Using KnownType and DataContract did not help me, and when i created same classes in a client app, i have exceptions. Please, help?
I fixed it: basically i created dummy methods that returned object of nedded types, deleted the method references from client app and it worked.

Passing values from concretized instance of an base class to another base class instance

I am currently working on making viewmodels capable of parsing data extracted from database to the UI and vice versa, and to do so I do a lot of manual mapping between my two viewmodels.
Currently I try to pass some values that determines an attribute, but since each attributetype requires specifying a lot specific parameter, and 90% of the variables will be redundant in all cases since attributes only have one type..
Thus i have create a placeholder base class, which just contains an Id, that each atttribute have,
and each of the specific attribute type parameter will then use this placeholder as base class..
example:
public class BooleanViewSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeViewSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class AttributeView
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeViewSpecification { get; set; }
}
And the same Goes for my DB view model
public class BooleanSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class Attribute
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeSpecification { get; set; }
}
Problem is then mapping from one class to another class
public static IEnumerable<AttributeView> MapToViewModel(this IEnumerable<Attribute> attributes)
{
return attributes.Select(z => new AttributeView()
{
Type = z.Type,
AttributeTypeViewSpecification = z.AttributeTypeSpecification
});
}
Which does not seem to work?
I use entity framework and migrate using Code-First what I receive is the Id of the location, and not the actual values?
I cant seem to understand why I cant be given the values - if it during the mapping does have the value?
So why cant they be mapped over?
I retrieve the value
Context.Include(Attribute).ThenInclude(AttributeTypeSpecification)
The only thing I receive is the actual Id rather than the specified entries?

EF code first: inheriting from common base class, WEB api losing base properties

I would like to use the following as a base class for all my classes:
[DataContract(IsReference = true)]
public abstract class EsBase
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public Guid ID { get; set; }
public bool SoftDelete { get; set; }
}
With example child class:
public class Match : EsBase
{
[Display(Name = "Start time")]
public DateTime StartTime { get; set; }
}
Problem is that when Match object is sent out through WEB API I do not have access to ID or SoftDelete.
How to pass these as well into output?
Just add [DataMember] attribute to the properties of your DataContract class. This then makes those properties become part of the serialization of your DataContract object.

Using custom classes in WCF Test Client

As part of my WCF web service's return message I created three custom classes. They are implemented in my the return message class, which contains a DataContract decoration (pretty sure that's how it's supposed to be done).
However when I run the Visual Studio 2012 WCF Test Client I get the following error message (highlighted in black)
App Code
Class exposed to the program calling the web service. This calls a method with a return type of CloneMessage (detailed below)
namespace OKeeffeDataService
{
public class MonetToDss : IMonetToDss
{
private AgentCloneRules _agentClone;
public MonetToDss()
{
_agentClone = new AgentCloneRules();
}
[PrincipalPermission(SecurityAction.Demand, Role = "AgentPaymentUpdater")]
public CloneMessage CloneRequest(string agentId)
{
//TODO: Validate agent Id?
EventLog.WriteEntry("OKeeffe", "Made it to CloneRequest", EventLogEntryType.Information);
return _agentClone.CloneRequest(agentId);
}
}
}
App Code Interface
namespace OKeeffeDataService
{
[ServiceContract]
public interface IMonetToDss
{
[OperationContract]
CloneMessage CloneRequest(string agentId);
}
}
Clone Message Class
This is the class the WCF service returns. The AgentClone and RelationshipCode classes were generated by the Entity Framework and extend System.Data.Objects.DataClasses.EntityObject. AgentAddresses is a custom class I wrote with standard string properties representing Street, City, State, Zip, etc (listed below).
namespace BusinessEntities
{
[DataContract]
public class CloneMessage : ICloneMessage
{
[DataMember]
public AgentClone AgentInformation { get; set; }
[DataMember]
public IList<AgentAddress> AgentAddresses { get; set; }
[DataMember]
public IList<RelationshipCode> RelationshipCodes { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
public CloneMessage(){}
public CloneMessage(AgentClone agtTran, IList<AgentAddress> addresses, IList<RelationshipCode> relationshipCodes)
{
this.AgentInformation = agtTran;
this.AgentAddresses = addresses;
this.RelationshipCodes = relationshipCodes;
}
}
}
Clone Message Interface
namespace BusinessEntities
{
public interface ICloneMessage
{
AgentClone AgentInformation { get; set; }
IList<AgentAddress> AgentAddresses { get; set; }
IList<RelationshipCode> RelationshipCodes { get; set; }
String ErrorMessage { get; set; }
}
}
EDIT
Adding the enum and classes to the post
AgentAddresses class
AddressType is custom enum.
namespace BusinessEntities
{
[DataContract]
public class AgentAddress : IAgentAddress
{
[DataMember]
public AddressTypeValues.AddressType AddressType { get; set; }
[DataMember]
public string Street1 { get; set; }
[DataMember]
public string Street2 { get; set; }
[DataMember]
public string Street3 { get; set; }
[DataMember]
public string City { get; set; }
[DataMember]
public string State { get; set; }
[DataMember]
public string ZipCode { get; set; }
}
}
AddressTypeValues enum
namespace BusinessEntities
{
public class AddressTypeValues
{
[DataContract(Name = "AddressType")]
public enum AddressType
{
[EnumMember(Value = "Home")]
Home,
[EnumMember(Value = "Mailing")]
Mailing,
[EnumMember(Value = "Location")]
Location,
[EnumMember(Value = "Other")]
Other
}
}
}
AgentClone and RelationshipCode class headers
[EdmEntityTypeAttribute(NamespaceName="AgentResourcesReturn", Name="AgentClone")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class AgentClone : EntityObject
[EdmEntityTypeAttribute(NamespaceName="AgentResourcesReturn", Name="RelationshipCode")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class RelationshipCode : EntityObject
Try adding the following known types to your CloneMessage data contract.
[DataContract]
[KnownType(typeof(AgentClone))]
[KnownType(typeof(AgentAddress))]
[KnownType(typeof(RelationshipCode))]
public class CloneMessage : ICloneMessage
And this AddressTypeValues type to the AgentAddress class.
[DataContract]
[KnownType(typeof(AddressTypeValues))]
public class AgentAddress : IAgentAddress
Once you do this, rebuild the service and try to browse it again the WCF test client.
Add DataContract attribute to AgentClone & RelationshipCode classes
If AddressTypeValues.AddressType is Enum type, then apply the DataContractAttribute attribute to the type. You must then apply the EnumMemberAttribute attribute to each member that must be included in the data contract. refer - http://msdn.microsoft.com/en-us/library/aa347875(v=vs.110).aspx
Add the below attributes to CloneMessage class
[KnownType(typeof(AgentAddress))]
[KnownType(typeof(RelationshipCode))]
try changing like this..
namespace BusinessEntities
{
[DataContract(Name = "AddressType")]
public enum AddressType
{
[EnumMember(Value = "Home")]
Home,
[EnumMember(Value = "Mailing")]
Mailing,
[EnumMember(Value = "Location")]
Location,
[EnumMember(Value = "Other")]
Other
}
}
[DataMember]
public AddressType AddressType { get; set; }
If you are still facing issue, then I am 100% sure that the problem is with AgentInformation/RelationshipCodes. Just comment these two members of CloneMessage class and try. you will get some pointers. If you don't face issue after commenting, then it is something to do with EntityObject. similar issue - Why doesn't WCFTestclient understand standard EF objects but understands STE objects

DataContract and inheritance?

How to use DataContract with inheritance? Will code below work?
[DataContract]
public class ConsoleData
{
[DataMember]
public String Description { get; set; }
}
[DataContract]
public class SomeData : ConsoleData
{
[DataMember]
public int Volume { get; set; }
......
Yes, that would work.
The DataContractAttribute has Inherited set to false, so it is necessary to apply the attribute to both the child class and the parent class (as you have done in the question).
You would need to use the KnownType attribute if you want to use your data contracts with polymorphism.
For example
[ServiceContract]
interface MyWcfContract
{
[OperationContract]
HandleData(ConsoleData contractData);
}
If you invoked the method like so:
SomeData someData = new SomeData { Description = "Test", Volume = 30 };
// The method is expecting a ConsoleData instance,
// I'm passing a SomeData instance instead
myWcfProxy.HandleData(someData);
Then the deserializer on the service end will not know that it's an instance of SomeData, just an instance of ConsoleData which it was expecting.
The way to fix this is to register the SomeData class as a known type of the ConsoleData.
[DataContract]
[KnownType(typeof(SomeData))]
public class ConsoleData
{
[DataMember]
public String Description { get; set; }
}
[DataContract]
public class SomeData : ConsoleData
{
[DataMember]
public int Volume { get; set; }
......
You'll need to use the KnownType attribute if you are using the XmlSerializerFormat for your ServiceContract:
[DataContract]
public class ConsoleData
{
[DataMember]
public String Description { get; set; }
}
[DataContract, KnownType(typeof(ConsoleData))]
public class SomeData : ConsoleData
{
[DataMember]
public int Volume { get; set; }
}

Categories

Resources