MarimerLLC / csla

A home for your business logic in any .NET application.
https://cslanet.com
MIT License
1.23k stars 394 forks source link

Serialization of portal broken for an array of objects #4057

Closed kant2002 closed 1 week ago

kant2002 commented 1 week ago

Describe the bug When trying to use myPortal.ExecuteAsync() with a serializable object. I've used it previously for a CreateChildAsync() call without any issues. But with the .ExecuteAsync(myParameter) I now get the following exception:

Serialization of type object is not supported. (System.Object[])
   at Csla.DataPortalClient.DataPortalProxy.Fetch(Type objectType, Object criteria, DataPortalContext context, Boolean isSync)
   at MyDataPortalCache.GetOrCreate(Type objectType, Object criteria, Func`1 getFunc) in 
   at MyCachingDataPortalProxyDecorator.Fetch(Type objectType, Object criteria, DataPortalContext context, Boolean isSync) in 
   at Csla.DataPortal`1.<>c__DisplayClass25_0.<<DoExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Csla.DataPortalClient.DataPortalNoCache.GetDataPortalResultAsync(Type objectType, Object criteria, DataPortalOperations operation, Func`1 portal)
   at Csla.DataPortal`1.DoExecuteAsync(Type objectType, Object criteria, Boolean isSync)
   at Csla.DataPortal`1.DoFetchAsync(Type objectType, Object criteria, Boolean isSync)
   at Csla.DataPortal`1.ExecuteAsync(Object[] criteria)

Because parameters are treated as params object[] criterias my single object is the only element within the object[] -Array. And that produces a hicup. Only for Execute not CreateChild or Fetch.

I had that some time ago, too. Tried to reproduce it with a simple console and in memory stuff. But there it just works. So I think it's the HttpProxy having problems here

Originally reported by @StefanOssendorf

kant2002 commented 1 week ago

Would like to take a look at this.

StefanOssendorf commented 1 week ago

I can reproduce this issue with the example BlazorExample. I've downgraded the solution to CSLA 8.2.3 or else I couldn't build it due to a missing pre-release package of v9.

  1. Add the following classes to the BusinessLibrary project:

    
    [Serializable]
    public class FooCommand : CommandBase<FooCommand> {
    
    [Execute]
    private void Execute(Guid? id) {
     _ = id;
    }
    
    [Execute]
    private void Execute(TestBar bar) {
    var x = bar;
    }
    }

public class TestBar : MobileObject { public string MyProperty { get; set; }

protected override void OnGetState(SerializationInfo info, StateMode mode) { base.OnGetState(info, mode); info.AddValue(nameof(MyProperty), MyProperty); }

protected override void OnSetState(SerializationInfo info, StateMode mode) { base.OnSetState(info, mode); MyProperty = info.GetValue(nameof(MyProperty)); } }

2. Replace the method body of `IncrementCount` in the `BlazorExample.Client.Components.Pages.Counter.razor` file with the following body:
```csharp
private async Task IncrementCount()
{
    currentCount++;
    applicationContext.LocalContext["counter"] = currentCount;
    var portal = applicationContext.GetRequiredService<IDataPortal<FooCommand>>();
    //_ = await portal.ExecuteAsync(new TestBar { MyProperty = "show me the error" });
    _ = await portal.ExecuteAsync(Guid.NewGuid());
}
  1. Now start the BlazorExample project
  2. Make sure to open all navigation links at least once
  3. Wait a moment to allow the browser to download the WASM client - this is the important part
  4. Go to the counter page
  5. Hit Click me
  6. Get the banner An unhandled error has occurred. [Reload](https://localhost:7210/) with the reported exception from the initial post.