I'm using the svcutil tool to generate a set of proxies for a 3rd party wdsl. One of the types, defined in an associated XSD file uses the xs:any element:
<xs:any namespace="##any" processContents="lax"/>
The code produced uses a property of type XmlElement to represent this:
[System.Xml.Serialization.XmlAnyElementAttribute(Order=0)]
public System.Xml.XmlElement Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
What actually needs to go in this field is one of the strongly-typed objects also generated by the tool.
My question is: is there an easy/recommended way to get from an instance of the object to an instance of XmlElement?
All I can think of is serializing the object graph into a XmlDocument and then using that. But that seems awkward.
The generated code is correct for the schema. xs:any mas to a xml blob. You will need to change the schema from xs:any to the specific type if you want the generated code to be more specific.
However, if the schema is not under your control, this is the only correct way to consume the schema. You cannot assume that a message contains any specific type.
Related
We already have flatbuffer library embedded in our software code for simple schemas with JSON output data generation.
More update: We are generating the header files using flatc compiler against the schema and integrate these files inside of our code along with FB library for further serialization/deserialization.
Now we also need to have the following schema tree to be supported.
namespace SampleNS;
/// user defined key value pairs to add custom metadata
/// key namespacing is the responsibility of the user
table KeyValue {
key:string (key, required);
value:string (required);
}
enum SchemaVersion:byte {
V1,
V2
}
table Sometable {
value1:ubyte;
value2:ushort (key);
}
table ComponentData {
inputs: [Sometable];
outputs: [Sometable];
}
table Node {
name:string (key);
/// IO definition
data:ComponentData;
/// nested child
child:[Components];
}
table Components {
type:ubyte;
index:ubyte;
nodes:[Node];
}
table GroupMasterData {
schemaversion:SchemaVersion = sampleNS::SchemaVersion::V1;
metainfo:[KeyValue];
/// List of expected components in the system
components:[Components];
}
root_type GroupMasterData;
As from above, table Components is nested recursively. The intention is components may have childs that have the same fields.
I have few queries:
Flatc didnt gave me any error during schema compilation for such
recursive nested tables. But is this supported during the field
access for such tables?
I tried to generate a sample json data file based on above data but I
could not see the field for schemaversion. I learned FB doesn't
serialize the default values. so, I removed the default value that I
assigned in the schema. But, it still doesnt write into the json data
file. On this I also learned we can forcefully write into the file
using force_defaults option. I don't know where is this is to be
put: in the attribute or elsewhere?
Can I create a struct of enum field?
Is their any API to set Flatbuffer options that we otherwise pass to the compiler arguments? or if not, may be I think we have to tinker with the FB library code. Please suggest.
Method 1:
In our serialization method, we do this:
flatbuffers::Parser* parser = new flatbuffers::Parser();
parser->opts.output_default_scalars_in_json = true;
Is this the right method or should I use any other API?
Yes, trees (and even DAG) structures are fully supported. The type definition is recursive, but the data will eventually have leaf nodes with an empty vector of children, presumably.
The integer value for V1 is 0, and that is also the default value for all fields with no explicit default assigned. Use --defaults-json to see this field when converting. Note that explicit versions in a schema is an anti-pattern, since schemas are naturally evolvable without breaking backwards compatibility.
You can put enum fields in structs, yes. Is that what you mean?
This question already has an answer here:
Newtonsoft JSON.net deserialization error where fields in JSON change order
(1 answer)
Closed 6 years ago.
I have the following method in my web api
public void Put(string id, [FromBody]IContent value) {
//Do stuff
}
I'm using backbone js to send the following JSON to the server using fiddler the value is null:
{
"id": "articles/1",
"heading": "Bar",
"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"
}
but if I add the $type property first in the JSON object the deserialization works fine, see:
{
"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples",
"id": "articles/1",
"heading": "Bar"
}
is it possible to configure newtonsoft to check for the $type property anywhere in the object instead of the first property or can I configure backbone so it always adds the $type property first in the JSON object?
I would very strongly recommend against configuring any serializer (including JSON.NET) to read the object type from the incoming payload. This has historically been the cause of a large number of vulnerabilities in web applications. Instead, change the public entry point to your action to take the actual type as a bound parameter, then delegate to an internal testable method if desired.
First, AFAIK, the code of Json.NET is optimized to avoid holding the whole object in memory just to read its type. So it's better to place $type as the first property.
Second, you can write your own JsonConverter which reads first to JObject (using Load method), manually reads $type property, gets type from serializer's SerializationBinder, creates the value and populates it from JObject.
Third, regarding security. While Json.NET's $type may sound like a good idea, it's often not. It allows Json.NET to create any object type from any assembly just by writing its type in JSON file. It's better to use custom SerializationBinder with a dictionary which allows only types which you specify. You can find an example in my private framework (it also supports getting values for $type from JsonObjectAttribute):
https://github.com/Athari/Alba.Framework/blob/742ff1aeeb114179a16ca42667781944b26f3815/Alba.Framework/Serialization/DictionarySerializationBinder.cs
(This version uses some methods from other classes, but they're trivial. Later commits made the class more complex.)
I had kind of the same question apparently, and someone found an answer. Not sure whats the appropriate way to share an answer and give him ALL the credit, but this is the link:
Newtonsoft JSON.net deserialization error where fields in JSON change order
and this is the guy:
https://stackoverflow.com/users/3744182/dbc
This will work in backbone, but I don't know if every browser will behave the same. There's no guarantee, basically, that every browser will keep the items in the order which they are added.
MyModel = Backbone.Model.extend({
// ...
toJSON: function(){
// build the "$type" as the first parameter
var json = {"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"};
// get the rest of the data
_.extend(json, Backbone.Model.prototype.toJSON.call(this));
// send it back, and hope it's in the right order
return json;
}
});
You're better of getting NewtonSoft's JSON deserializer to work without needing it in a specific position, though. Hopefully that will be possible.
I have created a WCF service that has multiple operation contracts defined. One of my contracts returns a collection of known types. The type is defined separately as a data contract.
When the collection is serialised by the DataContractSerializer the xml representation defines the name of the collection as
<ArrayOfMyType*></ArrayOfMyType>
I want to alter this to return it as
<MyTypes></MyTypes>
but can seem to find the required attribute within the documentation. I have used XmlRootAttribute in another part of the system but that is designed for the XMLSerialiser
Try to define custom collection type:
[CollectionDataContract(Name = "MyTypes", ItemName = "MyType")]
public class MyTypeList : List<MyType>
{ }
And use this type as return value from your operation.
I'm trying to transfer some user information in the header of the message through message inspectors.
I have created a behavior which adds the inspector to the service (both client and server).
But when I try to communicate with the service I get the following error:
XmlException:
Name cannot begin with the '<' character, hexadecimal value 0x3C.
I have also get exception telling me that DataContracts where unexpected.
Type
'System.DelegateSerializationHolder+DelegateEntry'
with data contract name
'DelegateSerializationHolder.DelegateEntry:http://schemas.datacontract.org/2004/07/System'
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.
The thing is that my object contains other objects which are marked as DataContract and I'm not interested adding the KnownType attribute for those types.
Another problem might be that my object to serialize is very restricted in form of internal class and internal properties etc.
Can anyone guide me in the right direction. What I'm I doing wrong?
Some code:
public virtual object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var header = MessageHeader.CreateHeader("<name>", "<namespace>", object);
request.Headers.Add(header);
return Guid.NewGuid();
}
Don't put the angle brackets into the actual strings. Remember, the serialization format may not even be text based, all you're doing is specifying the name of the element and the namespace. So your code should look more like this:
var header = MessageHeader.CreateHeader("name", "urn:myNamespace", object);
request.Headers.Add(header);
To close this question, I never solved the exception. Instead I implementated ISerializable which worked great for me.
It seems that serializing Entity Framework objects into JSON is not possible using either WCF's native DataContractJsonSerializer or ASP.NET's native JavaScript serializer. This is due to the reference counting issues both serializers reject. I have also tried Json.NET, which also fails specifically on a Reference Counting issue.
Edit: Json.NET can now serialize and deserialize Entity Framework entities.
My objects are Entity Framework objects, which are overloaded to perform additional business functionality (eg. authentication, etc.) and I do not want to decorate these classes with platform-specific attributes, etc. as I want to present a platform-agnostic API.
I've actually blogged about the individual steps I went though at https://blog.programx.co.uk/2009/03/18/wcf-json-serialization-woes-and-a-solution/
Have I missed something obvious?
The way I do this is by projecting the data I want to serialize into an anonymous type and serializing that. This ensures that only the information I actually want in the JSON is serialized, and I don't inadvertently serialize something further down the object graph. It looks like this:
var records = from entity in context.Entities
select new
{
Prop1 = entity.Prop1,
Prop2 = entity.Prop2,
ChildProp = entity.Child.Prop
}
return Json(records);
I find anonymous types just about ideal for this. The JSON, obviously, doesn't care what type was used to produce it. And anonymous types give you complete flexibility as to what properties and structure you put into the JSON.
Microsoft made an error in the way they made EF objects into data contracts. They included the base classes, and the back links.
Your best bet will be to create equivalent Data Transfer Object classes for each of the entities you want to return. These would include only the data, not the behavior, and not the EF-specific parts of an entity. You would also create methods to translate to and from your DTO classes.
Your services would then return the Data Transfer Objects.
Based off of #Craig Stuntz answer and similar to a DTO, for my solution I have created a partial class of the model (in a separate file) and a return object method with how I want it using only the properties that will be needed.
namespace TestApplication.Models
{
public partial class Employee
{
public object ToObject()
{
return new
{
EmployeeID = EmployeeID,
Name = Name,
Username = Username,
Office = Office,
PhoneNumber = PhoneNumber,
EmailAddress = EmailAddress,
Title = Title,
Department = Department,
Manager = Manager
};
}
}
}
And then I call it simply in my return:
var employee = dbCtx.Employees.Where(x => x.Name == usersName).Single();
return employee.ToObject();
I think the accepted answer is more quick and easy, I just use my method to keep all of my returns consistent and DRY.
My solution was to simply remove the parent reference on my child entities.
So in my model, I selected the relationship and changed the Parent reference to be Internal rather than Public.
May not be an ideal solution for all, but worked for me.
One more solution if you want to have better code consistency is to use JavaScriptConverter which will handle circular reference dependencies and will not serialize such references.
I've blogged about here:
http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/
FYI I found an alternative solution
You can set the parent relationship as private so then the properties are not exposed during the translation removing the infinite property loop
I battled with this problem for days,
Solution. Inside your edmx window.
- right click and add code generation item
- Select Code tab
- select EF 4x.POCOC Entity Generator
If you don't see it, then you will have to install it with nuget, search EF.
The Entity generator will generate all you complex type and entity object into simple classes to serialize into json.
I solved it by getting only object types from System namespace, and then convert them to Dictionary and then add them to list. Works good for me :)
It looks complicated, but this was the only generic solution that worked for me...
I'm using this logic for a helper I'm making, so it's for a special use where I need to be able to intercept every object type in entity object, maybe someone could adapt it to his use.
List<Dictionary<string, string>> outputData = new List<Dictionary<string, string>>();
// convert all items to objects
var data = Data.ToArray().Cast<object>().ToArray();
// get info about objects; and get only those we need
// this will remove circular references and other stuff we don't need
PropertyInfo[] objInfos = data[0].GetType().GetProperties();
foreach (PropertyInfo info in objInfos) {
switch (info.PropertyType.Namespace)
{
// all types that are in "System" namespace should be OK
case "System":
propeties.Add(info.Name);
break;
}
}
Dictionary<string, string> rowsData = null;
foreach (object obj in data) {
rowsData = new Dictionary<string, string>();
Type objType = obj.GetType();
foreach (string propertyName in propeties)
{
//if You don't need to intercept every object type You could just call .ToString(), and remove other code
PropertyInfo info = objType.GetProperty(propertyName);
switch(info.PropertyType.FullName)
{
case "System.String":
var colData = info.GetValue(obj, null);
rowsData.Add(propertyName, colData != null ? colData.ToString() : String.Empty);
break;
//here You can add more variable types if you need so (like int and so on...)
}
}
outputData .Add(rowsData); // add a new row
}
"outputData " is safe for JSON encode...
Hope someone will find this solution helpful. It was fun writing it :)