Skip to content

Commit

Permalink
Merge pull request #3669 from russblair/v7.x
Browse files Browse the repository at this point in the history
Fixes Blazor ViewModel Save doesn't call begin edit after save.
  • Loading branch information
rockfordlhotka authored Feb 5, 2024
2 parents 275f3fa + 6977ea1 commit facf71f
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 15 deletions.
1 change: 1 addition & 0 deletions Source/Csla.Blazor.Test/Fakes/FakePersonEmailAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace Csla.Blazor.Test.Fakes
{
[Serializable]
public class FakePersonEmailAddress : BusinessBase<FakePersonEmailAddress>
{
public static Csla.PropertyInfo<string> EmailAddressProperty = RegisterProperty<string>(nameof(EmailAddress));
Expand Down
1 change: 1 addition & 0 deletions Source/Csla.Blazor.Test/Fakes/FakePersonEmailAddresses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace Csla.Blazor.Test.Fakes
{
[Serializable]
public class FakePersonEmailAddresses : BusinessListBase<FakePersonEmailAddresses, FakePersonEmailAddress>
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Csla.Blazor.Test.Fakes;
using Microsoft.AspNetCore.Components.Forms;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using System;
using Csla.TestHelpers;
using System.Threading.Tasks;
using Csla.Core;

namespace Csla.Blazor.Test
{
[TestClass]
public class ViewModelEditChildListSaveEditLevelTests
{
private static TestDIContext _testDIContext;

[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
_testDIContext = TestDIContextFactory.CreateDefaultContext();
}

[TestMethod]
public async Task SaveModelChildListChange_ValidateEditLevel()
{
// Arrange
FakePerson person = GetValidFakePerson();
//EditContext editContext = new EditContext(person);
//editContext.AddCslaValidation();
var iuo = person as IUndoableObject;
var appCntxt = TestDIContextExtensions.CreateTestApplicationContext(_testDIContext);
var vm = new ViewModel<FakePerson>(appCntxt);
vm.ManageObjectLifetime = true;
vm.Model = person;

Assert.IsTrue(iuo.EditLevel > 0);
await vm.SaveAsync();
Assert.IsTrue(iuo.EditLevel == 1);

// Act
var eaddr = person.EmailAddresses.AddNew();
eaddr.EmailAddress = "[email protected]";
Assert.IsTrue(iuo.EditLevel > 0);
await vm.SaveAsync();

// Assert
Assert.IsTrue(iuo.EditLevel == 1);

}

#region Helper Methods

FakePerson GetValidFakePerson()
{
IDataPortal<FakePerson> dataPortal;
FakePerson person;

// Create an instance of a DataPortal that can be used for instantiating objects
dataPortal = _testDIContext.CreateDataPortal<FakePerson>();
person = dataPortal.Create();

person.FirstName = "John";
person.LastName = "Smith";
person.HomeTelephone = "01234 567890";

return person;
}

private string ConcatenateMessages(IEnumerable<string> messages)
{
return string.Join("; ", messages);
}

#endregion

}
}
23 changes: 16 additions & 7 deletions Source/Csla.Blazor/ViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,20 @@ public async Task SaveAsync()
{
UnhookChangedEvents(Model);

if (ManageObjectLifetime && Model is Core.ISupportUndo undoable)
var savable = Model as Core.ISavable;
if (ManageObjectLifetime)
{
// clone the object if possible
if (Model is ICloneable clonable)
savable = (Core.ISavable)clonable.Clone();

//apply changes
if (savable is Core.ISupportUndo undoable)
undoable.ApplyEdit();
}

IsBusy = true;
Model = await DoSaveAsync();
Model = await DoSaveAsync(savable);
Saved?.Invoke();
}
catch (DataPortalException ex)
Expand All @@ -261,15 +270,15 @@ public async Task SaveAsync()
/// Override to provide custom Model save behavior.
/// </summary>
/// <returns></returns>
protected virtual async Task<T> DoSaveAsync()
protected virtual async Task<T> DoSaveAsync(Core.ISavable cloned)
{
if (Model is Core.ISavable savable)
if (cloned != null)
{
var result = (T)await savable.SaveAsync();
var saved = (T)await cloned.SaveAsync();
if (Model is Core.IEditableBusinessObject editable)
new Core.GraphMerger(ApplicationContext).MergeGraph(editable, (Core.IEditableBusinessObject)result);
new Core.GraphMerger(ApplicationContext).MergeGraph(editable, (Core.IEditableBusinessObject)saved);
else
Model = result;
Model = saved;
}
return Model;
}
Expand Down
24 changes: 16 additions & 8 deletions Source/Csla.Xaml.Shared/ViewModelBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,20 @@ public virtual async Task<T> SaveAsync()
try
{
UnhookChangedEvents(Model);
var savable = Model as ISavable;
if (ManageObjectLifetime)
{
// clone the object if possible
if (Model is ICloneable clonable)
savable = (ISavable)clonable.Clone();

if (ManageObjectLifetime && Model is ISupportUndo undoable)
undoable.ApplyEdit();
//apply changes
if (savable is ISupportUndo undoable)
undoable.ApplyEdit();
}

IsBusy = true;
Model = await DoSaveAsync();
Model = await DoSaveAsync(savable);
}
finally
{
Expand All @@ -570,15 +578,15 @@ public virtual async Task<T> SaveAsync()
/// Override to provide custom Model save behavior.
/// </summary>
/// <returns></returns>
protected virtual async Task<T> DoSaveAsync()
protected virtual async Task<T> DoSaveAsync(ISavable cloned)
{
if (Model is ISavable savable)
if (cloned != null)
{
var result = (T)await savable.SaveAsync();
var saved = (T)await cloned.SaveAsync();
if (Model is IEditableBusinessObject editable)
new GraphMerger(ApplicationContext).MergeGraph(editable, (IEditableBusinessObject)result);
new GraphMerger(ApplicationContext).MergeGraph(editable, (IEditableBusinessObject)saved);
else
Model = result;
Model = saved;
}
return Model;
}
Expand Down

0 comments on commit facf71f

Please sign in to comment.