Skip to content
This repository has been archived by the owner on Jun 5, 2020. It is now read-only.

Child_XYZ Async no wait server response #922

Open
Cuiqs76 opened this issue Apr 9, 2020 · 7 comments
Open

Child_XYZ Async no wait server response #922

Cuiqs76 opened this issue Apr 9, 2020 · 7 comments

Comments

@Cuiqs76
Copy link

Cuiqs76 commented Apr 9, 2020

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

@rockfordlhotka
Copy link
Member

You should be able to do this:

  [UpdateChild]
  private async Task Update()
  {
    await WebApiCall();
  }

Your child data portal method needs to be async Task.

@Cuiqs76
Copy link
Author

Cuiqs76 commented Apr 9, 2020

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;
            }
        }

@rockfordlhotka
Copy link
Member

And this is with a server-side Blazor UI and a local data portal?

@Cuiqs76
Copy link
Author

Cuiqs76 commented Apr 10, 2020

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");
        }
    }

@rockfordlhotka
Copy link
Member

rockfordlhotka commented Apr 13, 2020

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?

@rockfordlhotka
Copy link
Member

I have a repro of this issue. Now to figure out what's happening.

@rockfordlhotka
Copy link
Member

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}");
        }
    }
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants