Yet another blog about WPF, Surface, SL, MVVM, NUI....

2010

Silverlight

Entries feed - Comments feed

 

[RIA Services] Why the client extended entities won't use the default backing store value ? EDITED

19 November 2010

The title may not be clear but I am talking about the entities that you extends on the client side using the fact that they are partial class. You may think as I was that if you add properties in them with backing store field, the properties will get initialed nicely : this is not the case and the property will always use the default value for the property type.

 

In this post we’ll discover how to perform our goal : create a property with the correct default value.

 

Take for example a Task entity in which you want to add a property IsVisible to tells the View if it should display it or not. By default, the Task should be visible. You will end up with this resulting code :

public partial class Task
{
//Default framework value for boolean is Falsek
private bool _isVisible = true;
public bool IsVisible
{
get
{
return _isVisible;
}
set
{
_isVisible = value;
}
}
}

 

But it won’t work and every loaded entity will have the IsVisible property to the default value which is Fase. Notice that I used the “loaded” verb and not “create” because the entity created use the correct value.

 

So why is it not working ?

In fact this is quite easy : when you load the entities, they are not created the usual way but de-serialized from the stream sended by the server so since the property is only on the client side, it wont be initialized with your value but with the default one. When you create entities, like the whole object is present on the client side and no de-serialisation is done, it will work as usual.

 

But RIA Services do not let us alone, the best practice is to initialize the default value of this kind in an override of the OnLoaded method. The final and working code should then be(take care to read the edit below after):

public partial class Task
{
protected override void OnLoaded(bool isInitialLoad)
{
base.OnLoaded(isInitialLoad);
IsVisible = true;
}
//Default framework value for boolean is Falsek
private bool _isVisible = true;
public bool IsVisible
{
get
{
return _isVisible;
}
set
{
_isVisible = value;
}
}
}

 

Hope this will save you the time to investigate I spend on this…

 

EDIT: In fact the entities are reloaded each time you submit changes and there is currently a bug (which will be fixed in the SP1  - as pointed out by Jeff in the comments) which will reset the value of your property to the default value even if it has been changed since.. But I have found a quite easy work around, by using two differents variables and knowing that RIA will simply ignore internal properties :

public partial class Task
{
protected override void OnLoaded(bool isInitialLoad)
{
base.OnLoaded(isInitialLoad);
//only for the initial load
if (isInitialLoad)
{
IsVisibleFix = true;
}
}
//Default framework value for boolean is Falsek
private bool _isVisible = true;
public bool _isVisible
{
//NO setter so RIA can't update the value
get { return _isVisible; }
}
//Internal so RIA ignore it and don't set the value
internal bool IsVisibleFix {
set { _isVisible = value; RaisePropertyChanged("DeleteVisibility"); }
}
}

 

You can read more on this forum post too : http://forums.silverlight.net/forums/t/203750.aspx

 

 

Shout itkick it on DotNetKicks.com

 

[RIA Services] How to force the validation of my entities (and just the validation !)

19 October 2010

RIA services solves for you a lot of problems and one of them is to add validations rules on the entities both on the client and on the server side. These differents rules are checked when you submit the changes from the client to the server or when you call “EndEdit” on the entities.

 

But there is times when you want to leverage the validation without submit the changes or commit your object modification (in a IEditableObject way of talking). In this post we will discover how to do just this.

 

 

Why don’t just call EndEdit() by the way ? Because by doing so you may push entities which are in a wrong state into the domain context with no way to revert to a correct state. Indeed, although the EndEdit method of the RIA entities launch the validation process and update the validations errors it does not stop the EndEdit from being performed even if there is errors.

So it may be a better idea to check if the Entity is in a correct state (no validation errors) before to call the EndEdit.

 

The little snippet to use is very simple and straightforward and it works well with the Silverlight toolkit dataform (if needed). It use the Validator class from the same assembly in which are the differents validations sttributes : System.ComponentModel.DataAnnotations.

 

/// <summary>
/// Validates the item and add its error in its validationErrors list.
/// </summary>
/// <param name="dataToValidate">The data to validate.</param>
/// <returns><code>True</code> if the object is valid, false otherwise.</returns>
public static bool ValidateItem(Entity dataToValidate, 
      out ICollection<ValidationResult> validationResults)
{
  if (dataToValidate == null) 
     throw new ArgumentNullException("dataToValidate");
 
  validationResults = new List<ValidationResult>();
  ValidationContext context = new ValidationContext(dataToValidate, null, null);
  Validator.TryValidateObject(dataToValidate, context, validationResults, true);
  dataToValidate.ValidationErrors.Clear();
  foreach (var res in validationResults)
  {
      dataToValidate.ValidationErrors.Add(res);
  }
  return validationResults.Count == 0;
}

 

Do you know any other way to perform this ?


Shout it kick it on DotNetKicks.com