首页 > 解决方案 > ASP.net Blazor:显示来自两个或多个相关表的数据

问题描述

https://www.youtube.com/watch?v=UBNRcaw1bDk&list=PL6n9fhu94yhVowClAs8-6nYnfsOTma14P&index=23

嗨,我正在尝试实施上述链接中提到的项目。我正在尝试从 ASP.NET WebAPI 项目中获取数据并在 Blazor 项目中使用。我从单个表中检索数据没有问题。但是当我尝试从 Secondary table 检索数据时。我在下面收到错误:

“HttpRequestException:响应状态码不表示成功:500(内部服务器错误)。”

在发送之前,我尝试将结果(在 API 项目中)显式转换为“Employee”类。没用。API 上的调试清楚地显示返回的员工带有部门信息,但在 Blazor 项目中收到错误。提前致谢!!

更新:

谢谢大家提供帮助。这是原始代码。

Models:
   public class Employee
    {
        public int EmployeeId { get; set; }
        [Required]
        [MinLength(2)]
        public string FirstName { get; set; }
        [Required]
        public string LastName { get; set; }
        public string Email { get; set; }
        public DateTime DateOfBrith { get; set; }
        public Gender Gender { get; set; }
        public int DepartmentId { get; set; }
        public Department Department { get; set; }
        public string PhotoPath { get; set; }
    }
    public class Department
    {
        public int DepartmentId { get; set; }
        public string DepartmentName { get; set; }
    }
EF:
public class EmployeeRepository : IEmployeeRepository
    {
    private readonly AppDbContext appDbContext;

    public EmployeeRepository(AppDbContext appDbContext)
    {
        this.appDbContext = appDbContext;
    }



    public async Task<Employee> GetEmployee(int employeeId)
    {
  // If I don't include Department table. I'm able to retrieve employee table data fine in Blazor project
        return await appDbContext.Employees
            .Include(e => e.Department)
            .FirstOrDefaultAsync(e => e.EmployeeId == employeeId);
    }
   }
API:
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeesController : ControllerBase
    {
        private readonly IEmployeeRepository employeeRepository;

        public EmployeesController(IEmployeeRepository employeeRepository)
        {
            this.employeeRepository = employeeRepository;
        }

        [HttpGet("{id:int}")]
            public async Task<ActionResult<Employee>> GetEmployee(int id)
            {
                try
                {
    
                    var result = await employeeRepository.GetEmployee(id);
    
                    if (result == null) return NotFound();
    //Breakpoint here returns data perfectly fine . With or without cast
                    return Ok(result);
                }
                catch (Exception)
                {
                    return StatusCode(StatusCodes.Status500InternalServerError,
                        "Error retrieving data from the database");
                }
            }
        }

 Call API in Blazor
 //Service 
 public interface IEmployeeService
 {
    Task<Employee> GetEmployee(int id);
 }
 public class EmployeeService : IEmployeeService
    {
        private readonly HttpClient httpClient;

        public EmployeeService(HttpClient httpClient)
        {
            this.httpClient = httpClient;
        }

 

   public async Task<Employee> GetEmployee(int id)
        {
//Error on receiving end 
            return await httpClient.GetJsonAsync<Employee>($"api/employees/{id}");
        }
}

 //Blazor Component Base class
  
  namespace EmployeeManagement.Web.Pages
    {
        public class EmployeeDetailsBase : ComponentBase
        {
            public Employee Employee { get; set; } = new Employee();

            [Inject]
            public IEmployeeService EmployeeService { get; set; }

            [Parameter]
            public string Id { get; set; }

            protected async override Task OnInitializedAsync()
            {
                Id = Id ?? "1";
                Employee = await EmployeeService.GetEmployee(int.Parse(Id));
            }
        }
    }



  // configuring in startup.cs 
   public void ConfigureServices(IServiceCollection services)
   {
    services.AddRazorPages();
    services.AddServerSideBlazor();

    services.AddHttpClient<IEmployeeService, EmployeeService>(client =>
    {
        client.BaseAddress = new Uri("https://localhost:44379/");
    });
   }
    Error: 
    HttpRequestException: Response status code does not indicate success: 500 (Internal Server Error).
    System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
    System.Net.Http.HttpClient.GetStringAsyncCore(Task<HttpResponseMessage> getTask)
    Microsoft.AspNetCore.Components.HttpClientJsonExtensions.GetJsonAsync<T>(HttpClient httpClient, string requestUri)
    XXXX.Services.EmployeeService.GetEmployee(int id) in EmployeeService.cs
    +
                    var item = await httpClient.GetJsonAsync<Employee>($"api/Employees/{id}");
    XXXX.Pages.EmployeeDetailsBase.OnInitializedAsync() in EmployeeDetailsBase.cs
    +
                    Employee = await EmployeeService.GetEmployee(int.Parse(Id));
    Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
    Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
    Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)
    Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
    Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessAsynchronousWork()
    Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, ParameterView initialParameters)
    Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterView initialParameters)
    Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterView initialParameters)
    Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+<>c__11<TResult>+<<InvokeAsync>b__11_0>d.MoveNext()
    Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.PrerenderComponentAsync(ParameterView parameters, HttpContext httpContext, Type componentType)
    Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.PrerenderedServerComponentAsync(HttpContext context, ServerComponentInvocationSequence invocationId, Type type, ParameterView parametersCollection)
    Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.RenderComponentAsync(ViewContext viewContext, Type componentType, RenderMode renderMode, object parameters)
    Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
    Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count)
    Praxis.EGPSystemBlazor.Pages.Pages__Host.<ExecuteAsync>b__14_1() in _Host.cshtml
    +
            <component type="typeof(App)" render-mode="ServerPrerendered" />
    Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync()
    Praxis.EGPSystemBlazor.Pages.Pages__Host.ExecuteAsync() in _Host.cshtml
    +
        Layout = null;
    Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
    Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
    Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
    Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
    Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
    Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
    Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
    Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

更新:感谢大家的回复。部门是强制性的,所以不可能为空。这是唯一有效的解决方案。我在 Blazor 项目中创建了另一个 Viewmodel,它的所有字段都与 ViewModelClass 中的 Employee 和 Initialized Department 相同。然后我能够在 UI 中显示 Employee.Department.DepartmentName。

public class EmployeeViewModel
 {
        public int EmployeeId { get; set; }
        [Required]
        [MinLength(2)]
        public string FirstName { get; set; }
        [Required]
        public string LastName { get; set; }
        public string Email { get; set; }
        public string ConfirmEmail { get; set; } 
        public DateTime DateOfBrith { get; set; }
        public Gender Gender { get; set; }
        public int DepartmentId { get; set; }
        public Department Department { get; set; }= new Department();
        public string PhotoPath { get; set; }
    }

标签: asp.netblazorblazor-server-sidehttp-errorasp.net-blazor

解决方案


Web API 项目是否也与 Web 浏览器中的客户端项目一样加载?

如果不是,您可能需要从解决方案资源管理器转到解决方案的属性以启动多个项目。

导航到 Web API 并在端口号后面的地址栏中键入以下字符串可能是个好主意:

/api/员工/1

然后,如果浏览器显示 Json 则一切正常。否则,您可以在 Web API 中设置断点并进一步调查错误发生的位置。

您可能想使用 Postman 之类的工具来测试 Web API。


推荐阅读