xml serialization error on bool types - asp.net

I am trying to find out how to solve the problem for serializing a type of bool from a camel case string.
I have the following xml
<Root>
<BoolElement>
False
</BoolElement>
</Root>
and the following class
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public bool BoolElement{get;set;}
}
this will produce an error.
If I use the same class and rename the "False" to "false" it will work. The problem is that I can't edit the xml.
Does anyone know how can I solve this?

You could use a backing field to aid for the deserialization of this invalid XML (I say invalid because according to the xsd:boolean schema False is an invalid value):
[XmlRoot("Root")]
public class RootObj
{
[XmlElement("BoolElement")]
public string BackingBoolElement
{
set
{
BoolElement = bool.Parse(value.ToLower());
}
get
{
return BoolElement.ToString();
}
}
[XmlIgnore]
public bool BoolElement { get; set; }
}

False is not a valid value for an xsd:boolean (but as you note false and 0 are) - if you cannot change the source data, then you could have a separate property purely for XML serialisation:
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public string BoolElementForSerialization
{
get
{
return (this.BoolElement ? "True" : "False");
}
set
{
this.BoolElement = (string.Compare(value, "false", StringComparison.OrdinalIgnoreCase) != 0);
}
}
[XmlIgnore]
public bool BoolElement{get;set;}
}

I created a new Boolean type that can deserialize from any string. It may not be perfect but it suited my needs at the time.
For the class you want to use simply change the data type from bool to SerializableBoolean:
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public SerializableBoolean BoolElement{get;set;}
}
You can then use the BoolElement property like any normal bool data type:
RootObj myObj = new RootObj();
if (myObj.BoolElement) { ... }
Here is the code for the SerializableBoolean class, note this code only handles deserializing, serializing to xml wasn't required for my purposes and so not implemented.
[System.Diagnostics.DebuggerDisplay("{Value}")]
public struct SerializableBoolean: System.Xml.Serialization.IXmlSerializable
{
private bool Value { get; set; }
public override bool Equals(object obj)
{
if (obj is string stringBoolean)
{
bool.TryParse(stringBoolean, out bool boolean);
return Value == boolean;
}
else if (obj is bool boolean)
{
return Value == boolean;
}
else if (obj is SerializableBoolean serializableBoolean)
{
return Value == serializableBoolean.Value;
}
else
{
return Value == Convert.ToBoolean(obj);
}
}
public override int GetHashCode()
{
return -1937169414 + Value.GetHashCode();
}
public XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
Value = Convert.ToBoolean(reader.ReadElementContentAsString());
}
public void WriteXml(XmlWriter writer)
{
throw new NotImplementedException();
}
public static bool operator ==(SerializableBoolean obj1, bool obj2)
{
return obj1.Value.Equals(obj2);
}
public static bool operator !=(SerializableBoolean obj1, bool obj2)
{
return !obj1.Value.Equals(obj2);
}
public static implicit operator SerializableBoolean(string value)
{
return new SerializableBoolean() { Value = Convert.ToBoolean(value) };
}
public static implicit operator SerializableBoolean(bool value)
{
return new SerializableBoolean() { Value = value };
}
public static implicit operator bool(SerializableBoolean b)
{
return b.Value;
}
}

Related

Reflection issue: NoSuchMethodException <init> ...specification.SearchCriteria, [Ljava.lang.String;)

Well, NoSuchMethodException is normally well self-explaining. Unfortunately, in my case, I couldn't even guess why I am getting such error.
I am taking care a code from other developer and I must maintain it. It was designed with specification pattern in mind. In order to make the search engine very generic, basically, any string passed from client to rest service is split in order to build the search criteria.
When executing "clazzSpec.getDeclaredConstructor(SearchCriteria.class, String[].class).newInstance(param);" I get
java.lang.NoSuchMethodException: br.com.mycompany.specification.SomethingSpecification.<init>(br.com.mycompany.specification.SearchCriteria, [Ljava.lang.String;)
Looking the image bellow, I can't see what is missed
SearchCriteria:
public class SearchCriteria {
private String key;
private String operation;
private Object value;
public SearchCriteria(String key, String operation, Object value) {
this.key = key;
this.operation = operation;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
SomethingSpecification
public class SomethingSpecification extends Specification<Something> {
public SomethingSpecification(SearchCriteria criteria) {
super(criteria);
}
#Override
public Predicate toPredicate(Root<Something> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
switch (criteria.getOperation()) {
case "=":
...
}
return super.toPredicate(root, query, builder);
}
}
The reflection code looks for a constructor with two arguments: SearchCriteria and a String[]. But the only constructor for SomethingSpecification only has one argument.

DateTime.Kind set to unspecified, not UTC, upon loading from database

When I create a Buyin object the response from the ASP.NET MVC controller, (return Json(response, JsonRequestBehavior.AllowGet);, looks like this:
"Buyin": {
"Id": 95,
"PlayerSessionId": 88,
"PlayerId": 45,
"PlayerName": "Alan",
"Amount": 888,
"BuyinType": "Credits",
"Description": null,
"Authorized": true,
"SignPath": "~/Signs/Buyins\\95.png",
"Payment": null,
"CreationDate": "/Date(1477242738042)/"
},
If I convert that on Epoch Converter I get this time: GMT: Sun, 23 Oct 2016 17:12:18.042 GMT
Looking in the database the stored datetime seems to be correct:
95 NULL 1 1 2016-10-23 17:12:18.043
When the response is sent out the Kind is set to UTC.
Now I call a controller to get all my data and all of the dates have several hours added to it:
{
"Id": 95,
"PlayerSessionId": 88,
"PlayerId": 45,
"PlayerName": "Alan",
"Amount": 888,
"BuyinType": "Credits",
"Description": null,
"Authorized": true,
"SignPath": "~/Signs/Buyins\\95.png",
"Payment": null,
"CreationDate": "/Date(1477267938043)/"
}
1477267938043 = GMT: Mon, 24 Oct 2016 00:12:18.043 GMT
However when I request this object I can see that the actual object has the correct date set:
But the Kind is set to Unspecified so I think this is causing the problem.
For the moment I don't have not set any globalization settings.
So basically my question is: When ASP.NET MVC loads the dates from the database is there a way to tell the server to load the dates with Kind set to UTC as I think that is the problem?
The database is saved and loaded using Entity Framework.
Update after the accepted answer
The accepted answer was great however my date values was already stored in the Database as UTC dates so I modified GetDateTime to this:
public override DateTime GetDateTime(int ordinal)
{
var date = base.GetDateTime(ordinal);
var utcDate = DateTime.SpecifyKind(date, DateTimeKind.Utc);
return utcDate;
//return base.GetDateTime(ordinal).ToUniversalTime();
}
Assuming you are using EF6 and you want to set the Kind property of any DateTime value retrieved from the database to Utc.
Similar questions have been asked, and the answers tend to suggest hooking into the ObjectContext.ObjectMaterialized event, but it didn't fire for queries that use projection.
The solution I'm going to propose works for both entity and projection queries, by performing the conversion at the DbDataReader level (which is used by this type of queries).
In order to do that, we need a custom DbDataReader implementation that intercepts the GetDateTime method. Unfortunately implementing DbDataReader derived class requires a lot of boilerplate code. Luckily I already created a base class form my answer to Dynamic Translate to avoid C# syntax errors which simply delegates each method to the underlying DbDataReader instance, so I'll just take it from there:
abstract class DelegatingDbDataReader : DbDataReader
{
readonly DbDataReader source;
public DelegatingDbDataReader(DbDataReader source)
{
this.source = source;
}
public override object this[string name] { get { return source[name]; } }
public override object this[int ordinal] { get { return source[ordinal]; } }
public override int Depth { get { return source.Depth; } }
public override int FieldCount { get { return source.FieldCount; } }
public override bool HasRows { get { return source.HasRows; } }
public override bool IsClosed { get { return source.IsClosed; } }
public override int RecordsAffected { get { return source.RecordsAffected; } }
public override bool GetBoolean(int ordinal) { return source.GetBoolean(ordinal); }
public override byte GetByte(int ordinal) { return source.GetByte(ordinal); }
public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) { return source.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length); }
public override char GetChar(int ordinal) { return source.GetChar(ordinal); }
public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) { return source.GetChars(ordinal, dataOffset, buffer, bufferOffset, length); }
public override string GetDataTypeName(int ordinal) { return source.GetDataTypeName(ordinal); }
public override DateTime GetDateTime(int ordinal) { return source.GetDateTime(ordinal); }
public override decimal GetDecimal(int ordinal) { return source.GetDecimal(ordinal); }
public override double GetDouble(int ordinal) { return source.GetDouble(ordinal); }
public override IEnumerator GetEnumerator() { return source.GetEnumerator(); }
public override Type GetFieldType(int ordinal) { return source.GetFieldType(ordinal); }
public override float GetFloat(int ordinal) { return source.GetFloat(ordinal); }
public override Guid GetGuid(int ordinal) { return source.GetGuid(ordinal); }
public override short GetInt16(int ordinal) { return source.GetInt16(ordinal); }
public override int GetInt32(int ordinal) { return source.GetInt32(ordinal); }
public override long GetInt64(int ordinal) { return source.GetInt64(ordinal); }
public override string GetName(int ordinal) { return source.GetName(ordinal); }
public override int GetOrdinal(string name) { return source.GetOrdinal(name); }
public override string GetString(int ordinal) { return source.GetString(ordinal); }
public override object GetValue(int ordinal) { return source.GetValue(ordinal); }
public override int GetValues(object[] values) { return source.GetValues(values); }
public override bool IsDBNull(int ordinal) { return source.IsDBNull(ordinal); }
public override bool NextResult() { return source.NextResult(); }
public override bool Read() { return source.Read(); }
public override void Close() { source.Close(); }
public override T GetFieldValue<T>(int ordinal) { return source.GetFieldValue<T>(ordinal); }
public override Task<T> GetFieldValueAsync<T>(int ordinal, CancellationToken cancellationToken) { return source.GetFieldValueAsync<T>(ordinal, cancellationToken); }
public override Type GetProviderSpecificFieldType(int ordinal) { return source.GetProviderSpecificFieldType(ordinal); }
public override object GetProviderSpecificValue(int ordinal) { return source.GetProviderSpecificValue(ordinal); }
public override int GetProviderSpecificValues(object[] values) { return source.GetProviderSpecificValues(values); }
public override DataTable GetSchemaTable() { return source.GetSchemaTable(); }
public override Stream GetStream(int ordinal) { return source.GetStream(ordinal); }
public override TextReader GetTextReader(int ordinal) { return source.GetTextReader(ordinal); }
public override Task<bool> IsDBNullAsync(int ordinal, CancellationToken cancellationToken) { return source.IsDBNullAsync(ordinal, cancellationToken); }
public override Task<bool> ReadAsync(CancellationToken cancellationToken) { return source.ReadAsync(cancellationToken); }
public override int VisibleFieldCount { get { return source.VisibleFieldCount; } }
}
and build the actual class that we need on top of it:
class UtcDateTimeConvertingDbDataReader : DelegatingDbDataReader
{
public UtcDateTimeConvertingDbDataReader(DbDataReader source) : base(source) { }
public override DateTime GetDateTime(int ordinal)
{
return DateTime.SpecifyKind(base.GetDateTime(ordinal), DateTimeKind.Utc);
}
}
Once we have that, we need to plug it into EF infrastructure using EF interception.
We'll start by creating a custom DbCommandInterceptor derived class:
class UtcDateTimeConvertingDbCommandInterceptor : DbCommandInterceptor
{
public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
base.ReaderExecuted(command, interceptionContext);
if (!(interceptionContext.Result is UtcDateTimeConvertingDbDataReader)
&& interceptionContext.Result != null
&& interceptionContext.Exception == null)
interceptionContext.Result = new UtcDateTimeConvertingDbDataReader(interceptionContext.Result);
}
}
register it (for instance from your DbContext derived class static constructor):
public class YourDbContext : DbContext
{
static YourDbContext()
{
DbInterception.Add(new UtcDateTimeConvertingDbCommandInterceptor());
}
// ...
}
and we are done.
Now every DateTime value coming from the database will have Kind property set to Utc.

How do I find settable properties with Json.NET using a ContractResolver? [duplicate]

Is there a way to ignore get-only properties using the Json.NET serializer but without using JsonIgnore attributes?
For example, I have a class with these get properties:
public Keys Hotkey { get; set; }
public Keys KeyCode
{
get
{
return Hotkey & Keys.KeyCode;
}
}
public Keys ModifiersKeys
{
get
{
return Hotkey & Keys.Modifiers;
}
}
public bool Control
{
get
{
return (Hotkey & Keys.Control) == Keys.Control;
}
}
public bool Shift
{
get
{
return (Hotkey & Keys.Shift) == Keys.Shift;
}
}
public bool Alt
{
get
{
return (Hotkey & Keys.Alt) == Keys.Alt;
}
}
public Modifiers ModifiersEnum
{
get
{
Modifiers modifiers = Modifiers.None;
if (Alt) modifiers |= Modifiers.Alt;
if (Control) modifiers |= Modifiers.Control;
if (Shift) modifiers |= Modifiers.Shift;
return modifiers;
}
}
public bool IsOnlyModifiers
{
get
{
return KeyCode == Keys.ControlKey || KeyCode == Keys.ShiftKey || KeyCode == Keys.Menu;
}
}
public bool IsValidKey
{
get
{
return KeyCode != Keys.None && !IsOnlyModifiers;
}
}
Do I need to add [JsonIgnore] to all of them (I also have many other classes), or there is better way to ignore all get-only properties?
You can do this by implementing a custom IContractResolver and using that during serialization. If you subclass the DefaultContractResolver, this becomes very easy to do:
class WritablePropertiesOnlyResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
return props.Where(p => p.Writable).ToList();
}
}
Here is a test program demonstrating how to use it:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
class Program
{
static void Main(string[] args)
{
Widget w = new Widget { Id = 2, Name = "Joe Schmoe" };
JsonSerializerSettings settings = new JsonSerializerSettings
{
ContractResolver = new WritablePropertiesOnlyResolver()
};
string json = JsonConvert.SerializeObject(w, settings);
Console.WriteLine(json);
}
}
class Widget
{
public int Id { get; set; }
public string Name { get; set; }
public string LowerCaseName
{
get { return (Name != null ? Name.ToLower() : null); }
}
}
Here is the output of the above. Notice that the read-only property LowerCaseName is not included in the output.
{"Id":2,"Name":"Joe Schmoe"}
Use the OptIn mode of JSON.net and you'll only need to decorate the properties you want to serialize. This isn't as good as automatically opting out all read only properties, but it can save you some work.
[JsonObject(MemberSerialization.OptIn)]
public class MyClass
{
[JsonProperty]
public string serializedProp { get; set; }
public string nonSerializedProp { get; set; }
}
Udate: Added another possibility using reflection
If the above solution still isn't quite what you're looking for, you could use reflection to make dictionary objects which would then be serialized. Of course the example below will only work for simple classes, so you would need to add recursion if your classes contain other classes. This should at least point you in the right direction.
The subroutine to put the filtered result into a dictionary:
private Dictionary<String, object> ConvertToDictionary(object classToSerialize)
{
Dictionary<String, object> resultDictionary = new Dictionary<string, object>();
foreach (var propertyInfo in classToSerialize.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (propertyInfo.CanWrite) resultDictionary.Add(propertyInfo.Name, propertyInfo.GetValue(classToSerialize, null));
}
return resultDictionary;
}
A snippet showing its use:
SampleClass sampleClass = new SampleClass();
sampleClass.Hotkey = Keys.A;
var toSerialize = ConvertToDictionary(sampleClass);
String resultText = JsonConvert.SerializeObject(toSerialize);
You can use a contract resolver like this:
public class ExcludeCalculatedResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = _ => ShouldSerialize(member);
return property;
}
internal static bool ShouldSerialize(MemberInfo memberInfo)
{
var propertyInfo = memberInfo as PropertyInfo;
if (propertyInfo == null)
{
return false;
}
if (propertyInfo.SetMethod != null)
{
return true;
}
var getMethod = propertyInfo.GetMethod;
return Attribute.GetCustomAttribute(getMethod, typeof(CompilerGeneratedAttribute)) != null;
}
}
It will exclude calculated properties but include C#6 get only properties and all properties with a set method.
Json.net does have the ability to conditionally serialize properties without an attribute or contract resolver. This is especially useful if you don't want your project to have a dependency on Json.net.
As per the Json.net documentation
To conditionally serialize a property, add a method that returns boolean with
the same name as the property and then prefix the method name with
ShouldSerialize. The result of the method determines whether the
property is serialized. If the method returns true then the property
will be serialized, if it returns false then the property will be
skipped.

Nullable datetime to datetime converter automapper

I have a situation where my DTOs require DateTime properties but my POCOs use nullable datetimes. To avoid having to create ForMember mappings for every property with this condition I created an ITypeConverter<DateTime?, DateTime>. The problem I ran into is when both DTO and POCO have nullable DateTimes this converter is called. The DestinationType is DateTime even though the property is a nullable datetime. Any idea how I would make this converter run only for actual nullable datetimes?
public class FooDTO
{
public DateTime? FooDate { get; set; }
}
public class FooPoco
{
public DateTime? FooDate { get; set; }
}
class Program
{
static void Main(string[] args)
{
Mapper.CreateMap<FooDTO, FooPoco>();
Mapper.CreateMap<DateTime?, DateTime>()
.ConvertUsing<NullableDateTimeConverter>();
var poco = new FooPoco();
Mapper.Map(new FooDTO() { FooDate = null }, poco);
if (poco.FooDate.HasValue)
Console.WriteLine(
"This should be null : {0}",
poco.FooDate.Value.ToString()); //Value is always set
else
Console.WriteLine("Mapping worked");
}
}
public class NullableDateTimeConverter : ITypeConverter<DateTime?, DateTime>
{
// Since both are nullable date times and this handles converting
// nullable to datetime I would not expect this to be called.
public DateTime Convert(ResolutionContext context)
{
var sourceDate = context.SourceValue as DateTime?;
if (sourceDate.HasValue)
return sourceDate.Value;
else
return default(DateTime);
}
}
I found this post AutoMapper TypeConverter mapping nullable type to not-nullable type but it was little help.
Without looking I suspect its calling your TypeCoverter because its the best match for the types being converted.
If you create another TypeConverter with the correct types it should work fine. Eg:
public class DateTimeConverter : ITypeConverter<DateTime?, DateTime>
{
public DateTime Convert(ResolutionContext context)
{
var sourceDate = context.SourceValue as DateTime?;
if (sourceDate.HasValue)
return sourceDate.Value;
else
return default(DateTime);
}
}
public class NullableDateTimeConverter : ITypeConverter<DateTime?, DateTime?>
{
public DateTime? Convert(ResolutionContext context)
{
var sourceDate = context.SourceValue as DateTime?;
if (sourceDate.HasValue)
return sourceDate.Value;
else
return default(DateTime?);
}
}
Note that if you wish these can be further simplified to
public class DateTimeConverter : TypeConverter<DateTime?, DateTime>
{
protected override DateTime ConvertCore(DateTime? source)
{
if (source.HasValue)
return source.Value;
else
return default(DateTime);
}
}
public class NullableDateTimeConverter : TypeConverter<DateTime?, DateTime?>
{
protected override DateTime? ConvertCore(DateTime? source)
{
return source;
}
}
Then just initialise both converters:
Mapper.CreateMap<DateTime?, DateTime>().ConvertUsing<DateTimeConverter>();
Mapper.CreateMap<DateTime?, DateTime?>().ConvertUsing<NullableDateTimeConverter>();
Mapper.AssertConfigurationIsValid();

How to retrieve an object's Property name/value pairs on a custom object?

I have a custom object with varying datatypes for each property.
I would like to be able to do something like:
public void evalCI(configurationItem CI)
{
foreach (PropertyInformation n in CI)
{
Response.Write(n.Name.ToString() + ": " + n.Value.ToString() + "</br>");
}
}
My custom object is:
public class configurationItem : IEnumerable
{
private string serial;
private string model;
private DateTime? wstart;
private DateTime? wend;
private Int32 daysLeft;
private string platform;
private string productVersion;
private string manufacturer;
private bool verificationFlag;
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
public string Serial
{
set { serial = value; }
get { return serial; }
}
public string Model
{
set { model = value; }
get { return model; }
}
public DateTime? Wstart
{
set { wstart = value; }
get { return wstart; }
}
public DateTime? Wend
{
set { wend = value; }
get { return wend; }
}
public Int32 DaysLeft
{
set { daysLeft = value; }
get { return daysLeft; }
}
public string Platform
{
set { platform = value; }
get { return platform; }
}
public string ProductVersion
{
set { productVersion = value; }
get { return productVersion; }
}
public string Manufacturer
{
set { manufacturer = value; }
get { return manufacturer; }
}
public bool VerificationFlag
{
set { verificationFlag = value; }
get { return verificationFlag; }
}
My expected output would be:
-Serial: 1234567
-Model: Mustang
-Wstart: 12/12/2005
-Wend: 12/11/2006
-DaysLeft: 0
-Platform: Car
-ProductVersion: GT
-Manufacturer: Ford
-VerificationFlag: true
At first I was getting an error that GetEnumerator() had to be implemented to use a foreach loop. The problem I keep running into is that all of the examples of Indexed Properties are of a single property with an indexable list, instead of an index for each property in the object. I was able to get intellisense to give me methods for PropertyInfo by adding:
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
However, the 2nd GetEnumerator() throws:
Compiler Error Message: CS0103: The name 'GetEnumerator' does not exist in the current context.
What am I missing here? How do I modify my object to give me the results I expect from evalCI()?
You don't need to implement IEnumerable. What you do need to do is use Reflection.
This is from memory, but I believe it would look like this:
foreach (PropertyInfo n in typeof(configurationItem).GetProperties())
{
Response.Write(string.Format("{0}: {1}<br/>", n.Name, n.GetValue(CI, null)));
}
This - the code as written - will also only give you public properties, and non-indexed properties (but it doesn't look like you have any indexed properties).

Resources