Child_XYZ Async no wait server response
Cuiqs76 opened this issue · comments
Question
If use async in child_XYZ to WebApi , the api no use Csla.
the vm.SaveAsync() no to wait the sever response.
if change child_xyz to sync use .result. the UI block.
Version and Platform
CSLA version: 5.1
OS: Windows,
Platform: Blazor assm ASP.NET Core
You should be able to do this:
[UpdateChild]
private async Task Update()
{
await WebApiCall();
}
Your child data portal method needs to be async Task
.
I test and UI block.
Prarent Model
[RunLocal]
[Insert]
private async Task Insert([Inject]Services.DataService service )
{
using (BypassPropertyChecks)
{
var data = new CreateRepairReportDto()
{
RepairDate = this.RepairDate,
RepairmanId = this.RepairmanId,
FromDepartment = this.FromDepartment,
OccurAt = this.OccurAt,
RmaNo = this.RmaNo,
ParentProductCode = this.ParentProductCode,
ParentProductName = this.ParentProductName,
ParentProductModel = this.ParentProductModel,
ParentProductSerialNo = this.ParentProductSerialNo,
ParentProductManufactureDate = this.ParentProductManufactureDate,
FaultPartCode = this.FaultPartCode,
FaultPartName = this.FaultPartName,
FaultPartModel = this.FaultPartModel,
FaultPartSerialNo = this.FaultPartSerialNo,
FaultPartManufactureDate = this.FaultPartManufactureDate,
FaultDescription = this.FaultDescription,
Remark=this.Remark,
};
this.Id= await service.AddAsync<CreateRepairReportDto>(AppSettings.RepairApiUrl, "api/v1/repairReports/add", data);
}
FieldManager.UpdateChildren(this.Id);
}
Child Model:
[InsertChild]
private async Task Insert(Guid parentId, [Inject]Services.DataService srv)
{
using (BypassPropertyChecks)
{
var item = new CreateRepairItemDto()
{
RepairReportId = parentId,
FaultItemCode = this.Code,
FaultItemName = this.Name,
FaultItemModel = this.Model,
Location = this.Location,
CauseId = this.CauseId,
CauseRemark = this.CauseRemark,
CauseTypeId = this.CauseTypeId,
ResponsibleUnit = this.ResponsibleUnit,
};
var id = await srv.AddAsync<CreateRepairItemDto>(AppSettings.RepairApiUrl, "api/v1/repairReports/add-item", item);
this.Id = id;
}
}
And this is with a server-side Blazor UI and a local data portal?
client-side (blazor assembly) and local data portal.
<PackageReference Include="Microsoft.AspNetCore.Blazor" Version="3.2.0-preview1.20073.1" />
<PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="3.2.0-preview1.20073.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Blazor.DevServer" Version="3.2.0-preview1.20073.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="3.2.0-preview3.20168.3" />
In UI code as below
private async void Submit()
{
await vm.SaveAsync();
if (vm.Exception == null)
{
matToaster.Add("Save success", MatToastType.Success, "Save");
}
else
{
matToaster.Add(vm.Exception.Message, MatToastType.Danger, "Save");
}
}
Client-side Blazor is single-threaded (at the moment) because webassembly is single-threaded. I am guessing that this is where the problem comes from, but I am not sure.
However, the data portal itself is able to make an HttpClient
call to the server and get a result, and that is async
.
And you are able to call the service for the parent, but not the child?
I have a repro of this issue. Now to figure out what's happening.
I take it back - I had a bug in my test code that caused an infinite loop. The data portal works as expected. Working code:
using Csla;
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace BlazorApp1.Client
{
[Serializable]
public class ValueEdit : BusinessBase<ValueEdit>
{
public static readonly PropertyInfo<string> ValueProperty = RegisterProperty<string>(nameof(Value));
public string Value
{
get => GetProperty(ValueProperty);
set => SetProperty(ValueProperty, value);
}
public static readonly PropertyInfo<ValueEdit> ChildProperty = RegisterProperty<ValueEdit>(nameof(Child));
public ValueEdit Child
{
get => GetProperty(ChildProperty);
set => SetProperty(ChildProperty, value);
}
[Fetch]
[FetchChild]
private async Task FetchAsync(string name, [Inject] HttpClient httpClient)
{
Console.WriteLine($"entering {nameof(FetchAsync)}-{name}");
var response = await httpClient.GetAsync("/api/value");
var value = await response.Content.ReadAsStringAsync();
Console.WriteLine($"after readstring {nameof(FetchAsync)}-{name}");
using (BypassPropertyChecks)
{
Value = value;
if (name != "child")
Child = await DataPortal.FetchChildAsync<ValueEdit>("child");
}
Console.WriteLine($"exiting {nameof(FetchAsync)}-{name}");
}
}
}