Csla..BusinessBase has a virtual Save method that I'm overriding in a class in order to perform some actions before the Save is executed. However, my overrided Save method is not being called. I'm using the ViewModelBase class from the Csla.Xaml namespace for my "Order" class. I called the Save method of ViewModel<T> which in turn calls BeginSave of ViewModelBase<T> that eventually calls the BeginSave method of the business object. The Save method of BusinessBase is never called so my override is never called as well. Is this a bug or a misuse on my part?
There is no virtual Save method in BusinessBase that I can find. There is however BeginSave method that you can override.
I'm assuming you're using CSLA 4 Beta.
Here's the code from, yes, CSLA 4 Beta, Csla.BusinessBase<T>:
public virtual T Save()
throw new NotSupportedException(Resources.NoSaveChildException);
if (EditLevel > 0)
throw new Rules.ValidationException(Resources.NoSaveEditingException);
if (!IsValid && !IsDeleted)
throw new Rules.ValidationException(Resources.NoSaveInvalidException);
throw new Rules.ValidationException(Resources.BusyObjectsMayNotBeSaved);
result = (T)DataPortal.Update(this);
result = (T)this;
OnSaved(result, null, null);
I did override BeginSave to make this work but this asynchronous way of saving an object is probably there for Silverlight's sake (mostly) but isn't calling Save directly still a viable option?
Aaaahhh yes sorry I've been working w/ silverlight mostly.
For some reason the ViewModelBase always uses the async version for save (i.e. BeginSave). So you can implement your changes on both the BeginSave and Save of your business object class. It would make it support both cases anyways. Just out of curiosity, what do you want to update before save? Because you can also implement that on the data portal side if possible.
It might be a bug in the ViewModelBase class. I think it should have called the DoSave instead of the BeginSave method for non silverlight ViewModelBase.
The reason I need to override Save is because I need to remove some items from a child collection first. It's very domain-specific. I'm working with an Order and OrderDetail objects and the OrderDetails collection is pre-populated with data from a set of customer preferences - products the customer usually orders. When a new order is created, the preferences are loaded into the OrderDetails collection. The user then needs to just enter the quantities of any products the customer will actually need for this order. Before doing a save I remove any OrderDetail objects that have a quantity of zero and were originally created via a preference. I have a business rule on the OrderDetail that allows these line items to be valid, otherwise a non-preference line item with a zero quantity is invalid.
I'm assuming the async methods are there because of Silverlight and Rocky has obviously made it so that these same methods can be used in WPF, WinForms and ASP.NET scenarios. That makes sense. However, it feels odd to me that I have to override both Save and BeginSave with the same functionality. I can make this work, just wondering if there's a better way such as a single method called SaveCore that both BeginSave and Save call. Make this virtual so I only need to override one method.
There are two methods: Save and BeginSave. In SL there's only BeginSave.
By default the viewmodel infrastructure uses the async options - I rarely use sync server calls in WPF, since I've become so used to being async in SL.
So you need to override BeginSave in your business class - or override the Save method in your viewmodel and invoke base.DoSave instead of base.BeginSave (which is the default). Also please note that DoSave doesn't exist in the SL version of ViewModelBase, because sync calls aren't available in SL.
Copyright (c) Marimer LLC