-5

I am using ASP.NET Core Blazor WebAssembly, .NET 5.0.1 , Entity Framework Core 5.0.1, Microsoft SQL Server, DevExpress Blazor WebAssembly 20.2.4 .

At Server project (ASP.NET Core Web API with Identity Server 4)

using acc.Server.Models;
using acc.Server.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace acc.Server.Controllers
{
    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class OrganizationUnitController : ControllerBase
    {

        private readonly ApplicationDbContext db;

        private readonly ILogger<OrganizationUnitController> _logger;

        public OrganizationUnitController(ILogger<OrganizationUnitController> logger, ApplicationDbContext _db)
        {
            _logger = logger;
            db = _db;
        }

        // https://localhost:5001/OrganizationUnit
        [HttpGet]
        public IEnumerable<OrganizationUnit> Get()
        {
            try
            {
                return db.OrganizationUnits.ToList();
            }
            catch
            {
                throw;
            }
        }


        // POST: https://localhost:5001/OrganizationUnit
        [HttpPost]
        public async Task<ActionResult<OrganizationUnit>> PostItem(OrganizationUnit item)
        {
            db.OrganizationUnits.Add(item);
            await db.SaveChangesAsync();
            return CreatedAtAction(nameof(GetItem), new { id = item.Id }, item);
        }

        // GET: https://localhost:5001/OrganizationUnit/5
        [HttpGet("{id}")]
        public async Task<ActionResult<OrganizationUnit>> GetItem(int id)
        {
            var item = await db.OrganizationUnits.FindAsync(id);
            if (item == null)
            {
                return NotFound();
            }
            return item;
        }

        // https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
        // https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-5.0&tabs=visual-studio

        // DELETE
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteItem(int id)
        {
            var item = await db.OrganizationUnits.FindAsync(id);
            if (item == null)
            {
                return NotFound();
            }

            db.OrganizationUnits.Remove(item);
            await db.SaveChangesAsync();
            return NoContent();
        }

        [HttpGet("GetGradeOfOrganizationUnit/{orgUnitId}")]
        public async Task<int> GetGradeOfOrganizationUnit(int orgUnitId)
        {
            var item = await db.OrganizationUnits.FindAsync(orgUnitId);
            int orgUnitGrade = 1;
            if (item.Grade != null)
            {
                orgUnitGrade = (int)item.Grade;
            }
            return orgUnitGrade;
        }
    }
}

At Client project (Blazor WebAssembly)

@page "/OrganizationUnitPage"
@inject HttpClient Http

<h3>Cơ cấu tổ chức</h3>

<DxDataGrid Data="@OrganizationUnits"
            ShowPager="true"
            RowRemoving="@((dataItem) => OnRowRemoving(dataItem))"
            RowInserting="@((newValues) => OnRowInserting(newValues))"
            RowUpdating="@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))"
            PagerPageSizeSelectorVisible="true"
            PagerAllowedPageSizes=@(new int[] {10,30,50})
            HorizontalScrollBarMode="ScrollBarMode.Visible"
            T="OrganizationUnit"
            ColumnResizeMode="@DataGridColumnResizeMode.Component"
            ShowFilterRow="true"
            CssClass="mw-1100"
            EditMode="DataGridEditMode.PopupEditForm">
    <HeaderTemplate>
        <DxToolbar>
            <DxDataGridColumnChooserToolbarItem Alignment="ToolbarItemAlignment.Right" Text="Chọn cột" Tooltip="Chọn cột" />
        </DxToolbar>
    </HeaderTemplate>
    <Columns>
        <DxDataGridCommandColumn Width="150px"></DxDataGridCommandColumn>
        <DxDataGridColumn Field="@nameof(OrganizationUnit.OrganizationUnitCode)" Caption="Mã đơn vị"></DxDataGridColumn>
        <DxDataGridColumn Field="@nameof(OrganizationUnit.OrganizationUnitName)" Caption="Tên đơn vị"></DxDataGridColumn>
        <DxDataGridColumn Field="@nameof(OrganizationUnit.Address)" Caption="Địa chỉ"></DxDataGridColumn>

        <DxDataGridComboBoxColumn T="ComboBoxItem"
                                  Field="@nameof(OrganizationUnit.Grade)"
                                  Caption="Cấp tổ chức"
                                  Data="@ListOfAccountTypes"
                                  ValueFieldName="@nameof(ComboBoxItem.ComboBoxItemValue)"
                                  TextFieldName="@nameof(ComboBoxItem.ComboBoxItemLabel)"
                                  Width="200px">
            <DisplayTemplate>
                @{
                    var foo = (context as OrganizationUnit).Grade;
                    int value = 0;
                    if (foo != null)
                    {
                        value = foo.Value;
                    }
                    string str = "";
                    switch (value)
                    {
                        case 1:
                            str = "Tổng công ty/Công ty";
                            break;
                        case 2:
                            str = "Phòng ban";
                            break;
                        default:
                            str = "";
                            break;
                    }
                    <div>@str</div>
                }
            </DisplayTemplate>
        </DxDataGridComboBoxColumn>
        <DxDataGridCheckBoxColumn Field="@nameof(OrganizationUnit.ActiveStatus)"
                                  Caption="Theo dõi"
                                  FilterTextChecked="Theo dõi"
                                  FilterTextUnchecked="Ngừng theo dõi"
                                  FilterTextIndeterminate="Không xác định"
                                  ValueChecked="@ActiveStatus.Active"
                                  ValueUnchecked="@ActiveStatus.NotActive"></DxDataGridCheckBoxColumn>
        <DxDataGridColumn Field="@nameof(OrganizationUnit.Id)" Caption="Id" Visible="false"></DxDataGridColumn>
    </Columns>
    <TotalSummary>
        <DxDataGridSummaryItem ShowInColumn=@nameof(OrganizationUnit.OrganizationUnitName) SummaryType=SummaryItemType.Count DisplayFormat="Số dòng: {0}" />
    </TotalSummary>
</DxDataGrid>

@code{
    IEnumerable<OrganizationUnit> OrganizationUnits;
    IEnumerable<ComboBoxItem> ListOfAccountTypes;

    public enum ActiveStatus
    {
        NotActive,
        Active
    }

    // Khởi tạo
    protected override async Task OnInitializedAsync()
    {
        OrganizationUnits = await Http.GetFromJsonAsync<OrganizationUnit[]>("OrganizationUnit");
        ListOfAccountTypes = new List<ComboBoxItem>()
    {
            new ComboBoxItem(0,"Dư Nợ"),
            new ComboBoxItem(1,"Dư Có"),
            new ComboBoxItem(2,"Lưỡng tính")
        };
    }

    public void OnRegionChanged()
    {
        InvokeAsync(StateHasChanged);
    }

    // Xóa
    void OnRowRemoving(OrganizationUnit organizationUnit)
    {
        Http.DeleteAsync("OrganizationUnit/" + organizationUnit.Id);
        InvokeAsync(StateHasChanged);
    }

    // Cập nhật
    void OnRowUpdating(OrganizationUnit organizationUnit, Dictionary<string, object> newValue)
    {
        foreach (var field in newValue.Keys)
        {
            switch (field)
            {
                case "OrganizationUnitCode": // Mã đơn vị
                    organizationUnit.OrganizationUnitCode = (string)newValue[field];
                    break;
                case "OrganizationUnitName": // Tên đơn vị
                    organizationUnit.OrganizationUnitName = (string)newValue[field];
                    break;
                case "ParentId": // Thuộc đơn vị
                    organizationUnit.ParentId = (int)newValue[field];
                    break;
                case "Grade": // Cấp tổ chức
                    organizationUnit.Grade = (int)newValue[field];
                    break;
                case "CostAccount": // Tài khoản chi phí lương
                    organizationUnit.CostAccount = (string)newValue[field];
                    break;
            }
        }
        organizationUnit.BranchId = 1;
        organizationUnit.IsSystem = false;
        if(organizationUnit.ParentId != null)
        {

        }
        if(organizationUnit.ParentId == null)
        {

        }
        // Lấy grade của parent
        string endPoint = "OrganizationUnit/GetGradeOfOrganizationUnit/" + organizationUnit.ParentId;
        int orgUnitParentGrade = await Http.GetFromJsonAsync<int>(endPoint);
        //int parentGrade =
        // Sau đó lấy grade của parent cộng thêm 1 để ra grade của Đơn vị hiện tại.
        organizationUnit.Grade = 3;
        // Lưu vào database.
        Http.PutAsJsonAsync("OrganizationUnit", organizationUnit);
        InvokeAsync(StateHasChanged);
    }

    // Thêm mới
    void OnRowInserting(Dictionary<string, object> newValue)
    {
        var organizationUnit = new OrganizationUnit();
        foreach (var field in newValue.Keys)
        {
            switch (field)
            {
                case "OrganizationUnitCode": // Mã đơn vị
                    organizationUnit.OrganizationUnitCode = (string)newValue[field];
                    break;
                case "OrganizationUnitName": // Tên đơn vị
                    organizationUnit.OrganizationUnitName = (string)newValue[field];
                    break;
                case "ParentId": // Thuộc đơn vị
                    organizationUnit.ParentId = (int)newValue[field];
                    break;
                case "Grade": // Cấp tổ chức
                    organizationUnit.Grade = (int)newValue[field];
                    break;
                case "CostAccount": // Tài khoản chi phí lương
                    organizationUnit.CostAccount = (string)newValue[field];
                    break;
            }
        }
        organizationUnit.BranchId = 1;
        organizationUnit.IsSystem = false;
        if (organizationUnit.ParentId != null)
        {

        }
        if (organizationUnit.ParentId == null)
        {

        }
        // Lấy grade của parent
        // Sau đó lấy grade của parent cộng thêm 1 để ra grade của Đơn vị hiện tại.
        organizationUnit.Grade = 3;
        // Lưu vào database.
        Http.PostAsJsonAsync("OrganizationUnit", organizationUnit);
        // Tạo ra sự thay đổi ở phía client mà không lấy lại dữ liệu từ phía database.
        // OrganizationUnits = (new OrganizationUnit[] { newItem }).Concat(OrganizationUnits);
        // Gọi lại dữ liệu từ database.
        InvokeAsync(StateHasChanged);
    }

    [Parameter] public string Action { get; set; }
    ElementReference input;
}

Focus at these lines (1)

string endPoint = "OrganizationUnit/GetGradeOfOrganizationUnit/" + organizationUnit.ParentId;
int orgUnitParentGrade = await Http.GetFromJsonAsync<int>(endPoint);

enter image description here

enter image description here

enter image description here

But the source code at (1) is syntax error. How to fix it?

Do Nhu Vy
  • 33,131
  • 37
  • 143
  • 202
  • I'd like to point out some issues with your question (which I think will explain downvotes). 1) It's way better for others to have a small piece of code to work with. Your question has enormous length, and it doesn't seem necessary. Backend code was redundant for example. 2) Text instead of screenshots of text/code is universally accepted as more user-friendly. Hope this helps! – pkuderov Jan 03 '21 at 15:39

2 Answers2

0

Can you change:

int orgUnitParentGrade = await Http.GetFromJsonAsync<int>(endPoint);

To:

var response = await Http.GetAsync(endPoint);
if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsStringAsync();
                var orgUnitParentGrade = JsonConvert.DeserializeObject<int>(data);
            }
else....
Serge
  • 7,259
  • 2
  • 7
  • 21
0

I think the real problem is that the method void OnRowUpdating(...) is not marked as asynchronous.

That's why your proposed solution worked - by forcing the asynchronous result to look like it's synchronous (that's what .Result does). But that's not how you should 'fix' such problems in general - this way you mix async and sync code. This's a very popular anti-pattern (part 4).

Better solution is to make you method OnRowUpdating asynchronous while keeping everything inside it as it was initially:

async Task OnRowUpdating(...)
{
    ...
    int orgUnitParentGrade = await Http.GetFromJsonAsync<int>(endPoint);
    ...
}

upd. After looking through your code again, I think that you should carefully go through OnRegionChanged, OnRowInserting, OnRowUpdating, OnRowRemoving, and for each one look for two things:

  1. They are asynchronous by nature, but each of them has synchronous signature. So you should make them async the same way I did for OnRowUpdating.

  2. They contain calls of asynchronous methods like Http.DeleteAsync, InvokeAsync and so on without awaiting their results. Are you sure that's intended? If not, await what should be awaited!

You can also check out documentation of the async programming model in .net to sharpen your understanding of it.

pkuderov
  • 3,064
  • 2
  • 25
  • 41