0

Using Telerik DataAccess, i have a Numeric(1,0) Field on my Database called chkSomething which was historically used to determine the state of a checkbox (you know, the tristate one)

0 - Unchecked
1 - Checked
2 - Neither Checked nor Unchecked

But the Kendo Checkbox is only a 2-State checkbox. So i thought i could just extend the Model:

public partial class TripleCheckboxModel
{
  private int _ID;
  public int ID { 
  get { return this._ID; }
  set { this._ID = value; } 
  }      
  private int _chkSomething;
  public int ChkSomething { 
  get { return this._chkSomething; }
  set { this._chkSomething = value; } 
  }

  [NotMapped]
  public bool BoolChkSomething { 
    get { return (this.ChkSomething == 1); }
    set { this._chkSomething = (value) ? 1 : 0; }
  }
}

Which works perfectly on client side:

@(Html.Kendo().CheckBoxFor(m => m.BoolChkSomething)

However when invoking a CRUD operation after toggling the checkbox like this one:

public ActionResult chk_Update([DataSourceRequest] DataSourceRequest request, TripleCheckboxModel updateItem)
{
    TripleCheckboxModel originalItem = this.dbContext.TripleCheckboxModels.FirstOrDefault(q => q.ID == updateItem.ID);

    // Here you can see the Issus
    originalItem.BoolChkSomething = updateItem.BoolChkSomething;

    this.dbContext.SaveChanges();
    return ...
}

It does not return the actual state the client chose, but the one which was initially set when the Item was loaded. I'm having a hard time tracking this Issue, as It seems that when converting the JSON back to the TripleCheckboxModel the setter from the BoolChkSomething property does not get invoked (or overwritten when the ChkSomething property gets assigned).

Is there a(n easier) way to get this running? (without changing the Database, as it is used by another application)

René
  • 11
  • 3

2 Answers2

0

I think you have to check the BoolChkSomething set code.

set { if (value = true) { this.ChkSomething = 1; } else { this.ChkSomething = 0;} }

should be:

set { this._chkSomething = (value) ? 1 : 0;}

because in your code you don't check the if value is true or false, but you are assigning true to value.

Teo
  • 125
  • 1
  • 11
  • Thank you for poiting this out, this way it could not work. I switched to your statement as it is much more elegant, but unfortunately this does not resolve the issue, as some properties now have the correct value, some don't, which directly points to the order the properties are assigned. – René Feb 22 '16 at 13:42
0

The answer is described here: Order of serialized fields using JSON.NET. As Deserialization works in the same order, you can ensure that the NotMapped properties do get resolved last, not to be overwritten by the other properties. Here is the relevant answer, which can be adapted to resolve this issue:

You can actually control the order by implementing IContractResolver or >overriding the DefaultContractResolver's CreateProperties method.

Here's an example of my simple implementation of IContractResolver which orders the properties alphabetically:

public class OrderedContractResolver : DefaultContractResolver
{
    protected override System.Collections.Generic.IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
    {
        return base.CreateProperties(type, memberSerialization).OrderBy(p => p.PropertyName).ToList();
    }
}

And then set the settings and serialize the object, and the JSON fields will be in alphabetical order:

var settings = new JsonSerializerSettings()
{
    ContractResolver = new OrderedContractResolver()
};

var json = JsonConvert.SerializeObject(obj, Formatting.Indented, settings);
Community
  • 1
  • 1
René
  • 11
  • 3