Failed to serialize Entity Framework class webapi - c#

I was searching for this issues but haven't found what I need. I need to use Entity Framework model in Web API for getting XML requests and responses.
I have two classes with a one-to-many relationship:
[Serializable]
[DataContract(Name = "shepherd")]
[KnownTypeAttribute(typeof(Sheep))]
public partial class Shepherd
{
public Shepherd()
{
this.Sheep = new HashSet<Sheep>();
}
[DataMember(Name = "shepherdId")]
//[XmlElement("shepherdId")]
public int Id { get; set; }
[DataMember(Name = "name")]
//[XmlElement("name")]
public string Name { get; set; }
[DataMember(Name = "isDeleted")]
//[XmlElement("IsDeleted")]
public Nullable<bool> IsDeleted { get; set; }
[DataMember(Name = "sheeps")]
//[XmlArray("sheeps"), XmlArrayItem("sheep")]
public virtual ICollection<Sheep> Sheep { get; set; }
}
and this is the second class:
[DataContract(Name = "sheep")]
[KnownType(typeof(Shepherd))]
public partial class Sheep
{
[DataMember(Name = "id")]
//[XmlElement("id")]
public int Id { get; set; }
[DataMember(Name = "colour")]
// [XmlElement("colour")]
public string Colour { get; set; }
[DataMember(Name = "createdon")]
//[XmlElement("CreatedOn")]
public Nullable<System.DateTime> CreatedOn { get; set; }
public int Shepherd { get; set; }
[IgnoreDataMember]
public virtual Shepherd Shepherd1 { get; set; }
}
and I always get this error:
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
System.InvalidOperationException
Type 'System.Data.Entity.DynamicProxies.Shepherd_EF797FA5FAF7ACF0AF313B6DFF83AF6E5F2EE1AD57BC457F9C10E73BA5DEEFE6' with data contract name 'Shepherd_EF797FA5FAF7ACF0AF313B6DFF83AF6E5F2EE1AD57BC457F9C10E73BA5DEEFE6:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
I need to get only XML not Json

Related

How to use automap with object with nested dto?

I am new to Automap, and I am trying to filter out the result. I want to know how to map nested dtos.
Post Entity:
public class Post
{
public Author? Author { get; set; }
[Required] [Key] public int Id { get; set; }
[Required] public string Title { get; set; }
[Required] public string Description { get; set; }
[Required] public string Body { get; set; }
}
PostRead: (dto)
public class PostRead
{
public DateTime Created { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public string Description { get; set; }
// Author would work but I want only the AuthorRead data
public AuthorRead Author;
}
Author Entity
public class Author
{
[Key] [Required] public int Id { get; set; }
[Required] public string Name { get; set; }
public IEnumerable<Post> Posts { get; set; }
}
AuthorRead.cs (dto)
public class AuthorRead
{
public int Id { get; set; }
public string Name { get; set; }
}
Technically if I use Author Entity in PostRead, it works but it'll give the list of the posts the Author has, and i want only the information that is in the AuthorRead (so the API response doesn't send the list of posts of the Author itself).
how I can map the object of type Author to the type AuthorRead in the PostRead?
Errors:
AutoMapper.AutoMapperMappingException : Missing type map configuration or unsupported mapping.
Mapping types:
Object -> PostRead
System.Object -> OhMyBlogAPI.Models.PostRead
at lambda_method22(Closure , Object , PostRead , ResolutionContext )
at OhMyBlogAPI.Tests.AutomapTests.MockPost_MapsTo_PostRead() in
What I tried , and searching a lot.
CreateMap<Post, PostRead>()
.ForMember(m
=> m.Author, o
=> o.MapFrom<Author, AuthorRead>("Author"));
And profiles (each line represent relevant profiles content):
CreateMap<Post, PostRead>();
CreateMap<Author, AuthorRead>();
My bad, the code works.
I misconfigured something in the Unit testing. I am really sorry.

NEST DBGeography

I am using Nest 6.2.0 to connect to elastic search.
I am trying to map a class containing DBGeography objects and I have tried adding the [GeoShape] tag and I get the following error.
ServerError = {ServerError: 400Type: mapper_parsing_exception Reason: "failed to parse" CausedBy: "Type: not_x_content_exception Reason: "Compressor detection can only be called on some xcontent bytes or compressed xcontent bytes""}
The code I am using to Create the index and document are:
// Create an index
response = Connection.CreateIndex(indexName, c => c
.Mappings(ms => ms
.Map<RACE.DataModels.EventModels.Event.Route>(m => m
.AutoMap<RACE.DataModels.EventModels.Event.Route>()
)
)
);
// Add document to index
result = Connection.Index(obj, i => i
.Index(indexName));
Also, here is the code for the Route object which I am trying to add to the index.
public partial class Route : BaseClass
{
[Key]
public Guid ID { get; set; }
[Required]
[Display(Name = "Event")]
public Guid EventID { get; set; }
[Required]
[Display(Name = "Route Name")]
public string Name { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
[Required]
[Display(Name = "Path Type")]
public int PathType { get; set; }
[GeoShape]
[Required]
[Display(Name = "Route Path")]
public DbGeography Path { get; set; }
//[GeoShape]
[Ignore]
public string PathWKT { get { return Path.WellKnownValue.WellKnownText; } }
[GeoShape]
[Display(Name = "Start")]
public DbGeography Start { get; set; }
[GeoShape]
[Display(Name = "End")]
public DbGeography End { get; set; }
[Display(Name = "Laps")]
public int Laps { get; set; }
[Display(Name = "Status")]
public int Status { get; set; }
[Ignore]
[ForeignKey("EventID")]
public virtual Event Event { get; set; }
[Ignore]
[ForeignKey("RouteID")]
public virtual List<Gateway> Gateways { get; set; }
}
Is DBGeography stopping the object from being correctly mapped, and how can I correctly map a DBGeography object to GeoShape?
NEST doesn't know how to serialize DbGeography types. The options you have are:
Write a JsonConverter that can serialize a DbGeography to geo_shape geoJSON that Elasticsearch supports, and hook up JsonNetSerializer from Nest.JsonNetSerializer nuget package to use this converter.
or
Map the DbGeography type to the respective IGeoShape type that NEST knows how to serialize, and use IGeoShape on your document POCO. You could probably leverage NetTopologySuite and types such as WKTReader to help with the conversion.
Elasticsearch 6.2.0 supports geo_shape input as WKT but this is not yet exposed in NEST; there's an open issue to add it in the next release. At the very least, I expect this to support deserializing WKT to NEST's IGeoShape.

WCF returning serialization exception when using .Net client but not Soap UI

I have an object called Organization that represents different rows in a database table called ORGANIZATION. Some organizations represent merchants and the merchant can have a "MerchantAux" record.
The Organization class looks like this:
[DataContract]
public class Organization : Core.Framework.BaseEntity
{
[Key]
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public virtual MerchantAux MerchantAuxRecord { get; set; }
public Organization()
{
}
}
The MerchantAux class looks like this:
[DataContract]
public class MerchantAux : BaseEntity
{
[Key]
[DataMember]
public int Code { get; set; }
[DataMember]
public int SettlementDelay { get; set; }
[DataMember]
public Nullable<System.Guid> WalletSiteId { get; set; }
[DataMember]
public bool? AddCardNotPresent { get; set; }
[DataMember]
public bool? BatchEmailNotification { get; set; }
[DataMember]
public string CsvEmailRecipients { get; set; }
[IgnoreDataMember]
public virtual ICollection<Organization> Organizations { get; set; }
public MerchantAux()
{
Organizations = new List<Organization>();
}
}
These objects are defined in a Models assembly. The WCF Service Assembly has a ServiceContract and OperationContracts to Get and Save Organizations.
Getting an organization works without issue. Saving an organization is failing with a VERY strange result.
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter boardingservice:organization. The InnerException message was 'The use of type 'MerchantAux' as a get-only collection is not supported with NetDataContractSerializer. Consider marking the type with the CollectionDataContractAttribute attribute or the SerializableAttribute attribute or adding a setter to the property.'. Please see InnerException for more details.
And there is no inner exception.
Oh yeah... Soap UI has no problem calling the Save method, but a .Net client throws the above error. Has anyone else seen this behavior where the serializer thinks that an object is a collection?
For the curious, I did try changing it to CollectionDataContract instead, but of course it fails straight away with an exception saying that MerchantAux doesn't implement IEnumerable (duh). Anyway... any ideas would be great.

XML deserialization cannot resolve attribute type

I am working on a project where I communicate with an API service through both REST and Comet semantics.
XML
So, the problem at hand.
I receive this error when I try to deserialize the following XML.
Error at resolve type "xsi:SubscriptionEvent"
NetBike.Xml.TypeResolvers.XmlTypeResolveException
Note: I use NetBike, but the error exist in the default xml formatter too
<?xml version="1.0" encoding="UTF-8"?>
<xsi:Event
xsi1:type="xsi:SubscriptionEvent"
xmlns:xsi="http://schema.broadsoft.com/xsi"
xmlns:xsi1="http://www.w3.org/2001/XMLSchema-instance">
<xsi:eventID>0787e727-e73d-43e0-a7b1-e968ba72ea53</xsi:eventID>
<xsi:sequenceNumber>1</xsi:sequenceNumber>
<xsi:userId>11111111#voip.company.domain</xsi:userId>
<xsi:externalApplicationId>NewClient</xsi:externalApplicationId>
<xsi:subscriptionId>24def51b-21fb-4d60-a1ef-67477dcafcfb</xsi:subscriptionId>
<xsi:channelId>575cfe44-2cc7-4cf5-bc05-bcc462bcbb02</xsi:channelId>
<xsi:targetId>22222222#voip.company.domain</xsi:targetId>
<xsi:eventData xsi1:type="xsi:ACDSubscriptionEvent"/>
</xsi:Event>
I'm not a XML "Jedi knight", but I know the basics.
The errors tells me I have a problem with the type xsi1:type="xsi:SubscriptionEvent" this is the attribute on the root xml (Event) element, this is the three attributes in question.
xsi1:type="xsi:SubscriptionEvent"
xmlns:xsi="http://schema.broadsoft.com/xsi"
xmlns:xsi1="http://www.w3.org/2001/XMLSchema-instance"
C# Class
I am using C#, until now I have had no problems creating equivalent classes based on the XML returned to me upon development.
If I take out the "bad data" the exception is avoided.
Event Class (I'm using this in Web API V2 environment, so technically its a model)
[XmlRoot(ElementName = "Event", Namespace = "http://schema.broadsoft.com/xsi")]
public class Event
{
[XmlElement(ElementName = "eventID", Namespace = "http://schema.broadsoft.com/xsi")]
public string EventID { get; set; }
[XmlElement(ElementName = "sequenceNumber", Namespace = "http://schema.broadsoft.com/xsi")]
public string SequenceNumber { get; set; }
[XmlElement(ElementName = "userId", Namespace = "http://schema.broadsoft.com/xsi")]
public string UserId { get; set; }
[XmlElement(ElementName = "externalApplicationId", Namespace = "http://schema.broadsoft.com/xsi")]
public string ExternalApplicationId { get; set; }
[XmlElement(ElementName = "subscriptionId", Namespace = "http://schema.broadsoft.com/xsi")]
public string SubscriptionId { get; set; }
[XmlElement(ElementName = "channelId", Namespace = "http://schema.broadsoft.com/xsi")]
public string ChannelId { get; set; }
[XmlElement(ElementName = "targetId", Namespace = "http://schema.broadsoft.com/xsi")]
public string TargetId { get; set; }
[XmlElement(ElementName = "eventData", Namespace = "http://schema.broadsoft.com/xsi")]
public EventData eventData { get; set; }
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string Type { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string xsi { get; set; }
[XmlAttribute(AttributeName = "xsi1", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi1 { get; set; }
[XmlRoot(ElementName = "eventData", Namespace = "http://schema.broadsoft.com/xsi")]
public class EventData
{
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string Type { get; set; }
}
}
This class was mainly generated from http://xmltocsharp.azurewebsites.net/
(that greatly speeds up this otherwise dull task)
Valid XML?
When I run the XML through different XML validators, I get different responses, some validates the XML fine, and some don't.
http://www.xmlvalidation.com: Fail
http://www.validome.org/xml/validate: Fail
http://codebeautify.org/xmlvalidate: Ok
To me, I find it hard to comprehend how exactly the structure is supposed to work.
It seems like the type attribute should be built upon the xsi1 attribute, but everything I have tried have failed.
My last resort will be to read the response as a string, then strip off the annoying XML so that it can be deserialized properly.
Best regards.
A slightly frustrated developer in dire need of help.
I think the confusion has arisen because xsi:type is part of XML schema and defines the types of various elements. You're trying to treat it as a normal attribute, and the serialiser is trying to use it to determine what objects to map the data to. The objects it's looking for aren't defined in the model.
Essentially, you need to model your classes after the type hierarchy your XML implies. So you have a base Event class with a SubscriptionEvent sub-class, and you have a base EventData class with a ACDSubscriptionEvent sub-class.
Note that (at least for XmlSerializer), you can omit a lot of your namespaces as they're inherited from the parent. You probably know more about the hierarchy than I do, so some of the properties may be able to be moved into the base class etc. Ideally, you'd have the XML schema file (.xsd) and would be able to generate the classes using xsd.exe, but this will work for the given XML:
[XmlInclude(typeof(SubscriptionEvent))]
[XmlRoot(Namespace = "http://schema.broadsoft.com/xsi")]
public abstract class Event
{
}
[XmlType(Namespace = "http://schema.broadsoft.com/xsi")]
public class SubscriptionEvent : Event
{
[XmlElement(ElementName = "eventID")]
public string EventID { get; set; }
[XmlElement(ElementName = "sequenceNumber")]
public string SequenceNumber { get; set; }
[XmlElement(ElementName = "userId")]
public string UserId { get; set; }
[XmlElement(ElementName = "externalApplicationId")]
public string ExternalApplicationId { get; set; }
[XmlElement(ElementName = "subscriptionId")]
public string SubscriptionId { get; set; }
[XmlElement(ElementName = "channelId")]
public string ChannelId { get; set; }
[XmlElement(ElementName = "targetId")]
public string TargetId { get; set; }
[XmlElement(ElementName = "eventData")]
public EventData EventData { get; set; }
}
[XmlInclude(typeof(ACDSubscriptionEvent))]
public abstract class EventData
{
}
[XmlType(Namespace = "http://schema.broadsoft.com/xsi")]
public class ACDSubscriptionEvent : EventData
{
}
See this fiddle for a working demo (using XmlSerializer).

How to model with EntityFramework extensible fields for the entities

I have the following requirement, on my app the Entities will come with some fields, however the user needs to be able to add additional fields to the entity and then values for those fields.
I was thinking something like this but I am not sure if it would be a good approach or not.
The base class is an entity (Not sure which fields I need to add here)
public class Entidad
{
}
Then the Company Class will inherit from Entity
public class Empresa : Entidad
{
[Key]
public int Id { get; set; }
public string Nombre { get; set; }
public string NIT { get; set; }
public string NombreRepresentanteLegal { get; set; }
public string TelefonoRepresentanteLegal { get; set; }
public string NombreContacto { get; set; }
public string TelefonoContacto { get; set; }
public ICollection<CampoAdicional> CamposAdicionales { get; set; }
}
As you can see there is an ICollection of additional fields. that class would have the fieldname, type and id
public class CampoAdicional
{
[Key]
public int Id { get; set; }
public string NombreCampo { get; set; }
public Tiposcampo TipoCampo { get; set; }
}
and then the field value would be something like this:
public class ValorCampo
{
public Entidad Entidad { get; set; }
public CampoAdicional Campo { get; set; }
public string ValorTexto { get;set ; }
public int ValorNumerico { get; set; }
}
However I am not sure if this is the correct model classes for my scenario and whether it would create the tables correctly.
EF works with lazy load so at least there are several "virtual" missings.
In all properties that does not use primitive types and in collections.
Can you extend more than one entity with additional fields? If so you need that ValorCampo contains the entity (Entidad) but the entity should have the Id so you need to move the Id from Empresa to Entidad. Otherwise you need ValorCampo should refer to Empresa not to Entidad

Categories

Resources