XmlSerializer stopped working after updates - silverlight

I'm using XmlSerializer. I've had no problems with it until now. I updated Silverlight from 4 to 5 and at the same time also updated the WCF RIA Services from v1 SP1 to v1 SP2. Now the following line gives me an error.
XmlSerializer s = new XmlSerializer(typeof(MyCustomObject));
The error is:
System.InvalidOperationException: System.ServiceModel.DomainServices.Client.EntityConflict cannot be serialized because it does not have a parameterless constructor.
The object I'm using (MyCustomObject in the sample) has not changed in any way so I'm starting to think it's either SL5 or the new RIA Services that is breaking my code. I didn't find any breaking changes document or mentions that this could happen. I don't know why it has a problem with EntityConflict since I'm not using any entities within my object.
Has anyone seen an error like this and/or know how to solve it?
UPDATE!
The final property that the error message says before EntityConflict is an Entity. I think that makes a difference but it has been working before. I'd also like to know why the serializer already tries to serialize the object in the constructor?

public static XmlSerializer GetEntityXmlSerializer<TEntity>()
where TEntity : Entity
{
XmlAttributes ignoreAttribute = new XmlAttributes()
{
XmlIgnore = true,
};
// use base class of Entity,
// if you use type of implementation
// you will get the error.
Type entityType = typeof(Entity);
var xmlAttributeOverrides = new XmlAttributeOverrides();
xmlAttributeOverrides.Add(entityType, "EntityConflict", ignoreAttribute);
xmlAttributeOverrides.Add(entityType, "EntityState", ignoreAttribute);
return new XmlSerializer(typeof(TEntity), xmlAttributeOverrides);
}

I am not sure why this would be happening, RIA Services entities are not XmlSerializable objects and the entities themselves are not decorated with the [Serializable] attribute. Have you added partial classes on the client side which decorate the entities with [Serializable] or modified the code generation in some way?

I got around this problem by using intermediary serializable POCO objects which were copies of my custom objects (which were inherited from Entity). The POCO objects did not inherit from Entity. I just updated their values from the original Entity objects. They then serialized quite nicely. Of course, when you de-serialize you need to update your Entity objects from the POCO objects.

Related

Entity Framework 5 Table Relationship

I use database first. In the auto-generated EF5 code:
Account has ClientID(FK)
Client has AddressID(FK)
Address has public List<EFClient> Clients { get; set; } (i did not specify this in DB but ef5 auto generated it)
When I serialize Address object, it throws exception "there is a circular reference" because the client collection in the address also cotains same address again
What can I do in this situation?
How can I not let EF5 auto-generate that Clients collection?
Thanks in advance!
I don't think you actually want to stop EF from auto-generating this navigation property, as it will affect lots of places. What you can do is simply remove the property that it generated from the model, which will remove the property from the class.

Error deserializing read-only property with Jackson

In My CXF-based REST layer I am using Jackson for seializing/deserializing Groovy objects. The issue I am experiencing deals with deserializing a property that does not have a setter method. There is a domain object Dashboard with getGroups() method returning a list of Group objects. Upon serialization this object is properly converted to JSON with "group" attribute. When I send the object for update from JavaScript, JSON still has the "group" attribute. Since the property is read-only on the domain object I would like to simply ignore the "group" property when deserializing JSON.
Since I am using Jackson mix-ins, I tried various combination of #JsonIgnore, #JsonGetter and #JsonProperty annotations - all to no avail. If the property is available upon serialization, I get the error below in deserialization. I can clean the JSON object in JavaScript by removing the "group" attribute, bit I would like to find a server-side solution.
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing 'setterless' property 'groups': get method returned null (through reference chain: org.ozoneplatform.commons.server.domain.model.DashboardTemplate["groups"])
at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.deserializeAndSet(SetterlessProperty.java:114)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:198)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:577)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:393)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:289)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1169)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:625)
at com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:448)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1038)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:614)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:578)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:238)
How can I tell Jackson to ignore a read-only property on deserialization?
Thank you,
Michael
After many fruitless hours, I have finally found the magic combination of spells that addresses such a seemingly trivial issue. In the mixin I had to create this combination of annotations:
#JsonIgnore
abstract Set<Group> groups
#JsonProperty
abstract Set<Group> getGroups()
#JsonIgnore
abstract void setGroups(Set<Group> groups)
On top of that I had to add two configuration parameters to the ObjectMapper:
mapper.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Isn't there a simpler way to achieve the same?
Michael
I had the same issue. Solution was to give the getter the correct name:
List list...
setList(...)
was correct, but my getter was
setProductList() which produced the "setterLess" error. changing it to:
setList(...) resolved the issue
I just ran into the same problem, and my solution was to create a private, no-op setter:
public class MyFoo {
public String getMyStr() {
return "hello, world";
}
private void setMyStr(String ignored) {}
}
Making setMyStr private prevents me from accidentally trying to call it from my code, but Jackson still finds it and invokes it. Little does jackson know -- or care -- that invoking it does nothing.

How to get can CanAddNew to be true for a collection returned by RIA Services

RIA Services is returning a list of Entities that won't allow me to add new items. Here are what I believe to be the pertinent details:
I'm using the released versions of Silverlight 4 and RIA Services 1.0 from mid-April of 2010.
I have a DomainService with a query method that returns List<ParentObject>.
ParentObject includes a property called "Children" that is defined as List<ChildObject>.
In the DomainService I have defined CRUD methods for ParentObject with appropriate attributes for the Query, Delete, Insert, and Update functions.
The ParentObject class has an Id property marked with the [Key] attribute. It also has the "Children" property marked with the attributes [Include], [Composition], and [Association("Parent_Child", "Id",
"ParentId")].
The ChildObject class has an Id marked with the [Key] attribute as well as a foreign key, "ParentId", that contains the Id of the parent.
On the client side, data is successfully returned and I assign the results of the query to a PagedCollectionView like this:
_pagedCollectionView = new PagedCollectionView(loadOperation.Entities);
When I try to add a new ParentObject to the PagedCollectionView like this:
ParentObject newParentObject = (ParentObject)_pagedCollectionView.AddNew();
I get the following error:
" 'Add New' is not allowed for this view."
On further investigation, I found that _pagedCollectionView.CanAddNew is "false" and cannot be changed because the property is read-only.
I need to be able to add and edit ParentObjects (with their related children, of course) to the PagedCollectionView. What do I need to do?
I was just playing around with a solution yesterday and feel pretty good about how it works. The reason you can't add is the source collection (op.Entities) is read-only. However, even if you could add to the collection, you'd still want to be adding to the EntitySet as well. I created a intermediate collection that takes care of both these things for me.
public class EntityList<T> : ObservableCollection<T> where T : Entity
{
private EntitySet<T> _entitySet;
public EntityList(IEnumerable<T> source, EntitySet<T> entitySet)
: base(source)
{
if (entitySet == null)
{
throw new ArgumentNullException("entitySet");
}
this._entitySet = entitySet;
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
if (!this._entitySet.Contains(item))
{
this._entitySet.Add(item);
}
}
protected override void RemoveItem(int index)
{
T item = this[index];
base.RemoveItem(index);
if (this._entitySet.Contains(item))
{
this._entitySet.Remove(item);
}
}
}
Then, I use it in code like this.
dataGrid.ItemsSource = new EntityList<Entity1>(op.Entities, context.Entity1s);
The only caveat is this collection does not actively update off the EntitySet. If you were binding to op.Entities, though, I assume that's what you'd expect.
[Edit]
A second caveat is this type is designed for binding. For full use of the available List operation (Clear, etc), you'd need to override a few of the other methods to write-though as well.
I'm planning to put together a post that explains this a little more in-depth, but for now, I hope this is enough.
Kyle
Here's a workaround which I am using:
Instead of using the AddNew, on your DomainContext you can retrieve an EntitySet<T> by saying Context.EntityNamePlural (ie: Context.Users = EntitySet<User> )
You can add a new entity to that EntitySet by calling Add() and then Context.SubmitChanges() to send it to the DB. To reflect the changes on the client you will need to Reload (Context.Load())
I just made this work about 15mins ago after having no luck with the PCV so I am sure it could be made to work better, but hopefully this will get you moving forward.
For my particular situation, I believe the best fit is this (Your Mileage May Vary):
Use a PagedCollectionView (PCV) as a wrapper around the context.EntityNamePlural (in my case, context.ParentObjects) which is an EntitySet. (Using loadOperation.Entities doesn't work for me because it is always read-only.)
_pagedCollectionView = new PagedCollectionView(context.ParentObjects);
Then bind to the PCV, but perform add/delete directly against the context.EntityNamePlural EntitySet. The PCV automatically syncs to the changes done to the underlying EntitySet so this approach means I don't need to worry about sync issues.
context.ParentObjects.Add();
(The reason for performing add/delete directly against the EntitySet instead of using the PCV is that PCV's implementation of IEditableCollectionView is incompatible with EntitySet causing IEditableCollectionView.CanAddNew to be "false" even though the underlying EntitySet supports this function.)
I think Kyle McClellan's approach (see his answer) may be preferred by some because it encapsulates the changes to the EntitySet, but I found that for my purposes it was unneccessary to add the ObservableCollection wrapper around loadOperation.Entities.
Many thanks to to Dallas Kinzel for his tips along the way!

Creating Test EntityList objects - RIA Services

I'm creating an EnityList to do some client side testing with my ViewModel. Something like:
var people = new EntityList<Person>()
{
new Incident() {Age = 55, Name="Joe"},
new Incident() {Age=42, Name="Sam"}
};
The problem is that the implicit (and explicit) Adds fail. The entitylist is created as read-only. Any thoughts on how to create a test EntityList?
If you're doing testing then you probably don't want an EntityList. I would expect that a ViewModel shouldn't know about the EntityList, but rather should just get access to an IEnumberable instead. Both EntityList and List expose this, so in your tests you can just create a List.
I realize this doesn't help with the issue of EntityList being read-only. :)
I think you also need an EntityContainer to own your EntityList.

How, WCF Ria Services can make a customised entity, known at client-side?

I constructed my Entity Model. One of my business objects,let's call it Store has a spatial data type. Very quickly I figured out that spatial fields aren't mapped via EF4. However I struggled my way out, by editing the xml declarations defining a query like the following:
<EntitySet Name="Stores" EntityType="Eltrun.OnShelfAuditModel.Store.Stores">
<DefiningQuery>
SELECT [rowId], [storeName], [location].STAsText() as location FROM Stores
</DefiningQuery>
</EntitySet>
At this point I decided to customize my Store entity via a partial class like this, just to make the conversion and still keep the SQLGeography data stored, returning just a double[] at client (as I cannot return neither SqlGeography, neither Location (Bing datatype).
public partial class Store
{
public double[] StoreLocation
{
get
{
SqlGeography geoLocation = SqlGeography.
STPointFromText(new SqlChars(this.location.ToCharArray()), 4326);
return new double[]{
(double)geoLocation.Lat,
(double)geoLocation.Long};
}
}
}
How can I make aware the Store data type of my little customization, at client project?
Thank you!
Just add a setter to your property, and the RIA Services code generator and serializer should create the equivalent property on the client's version of the Store class.
Hope that helps...

Resources