locked
Blazor Server + WebAPI/EF Core NET5.0 - returning properties from related tables RRS feed

  • Question

  • User379720387 posted

    I need help with understanding how I can present data from related Entities in Blazor Server.

    The current state of the my art is that I can present data from a single Entity on my razor page, with data coming from controllers inside the Api project which also has the EF Core Model.

    The operative sections of code:

    public DbSet<Transaction> Transactions { get; set; }  (in AppDbContext)

    [HttpGet] public async Task<ActionResult<List<Transaction>>> Get() => await context.Transactions .OrderByDescending(t => t.TransactionId) .ToListAsync();
    BtServer.Transaction[] transactions;
    
        protected async override Task OnInitializedAsync()
        {
            var httpClient = ClientFactory.CreateClient("ServerApi");
            httpClient.BaseAddress = new Uri(@"https://localhost:44317/");
            httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    
            transactions = await httpClient.GetFromJsonAsync<BtServer.Transaction[]>("api/Transaction");
        }

    VS tells me the blue highlighted Transaction in TransactionController is BtApiCore.Model.Transaction, that is the Entity Model for Transaction.cs created during the scaffolding. Which I understand.

    The green highlighted Transaction is BtServer.Transaction, which is interesting because there is no class called Transaction in the BtServer project. Thoughts?

    Moving past that, I am thinking this is somehow pointing to Transaction.cs the model that EF Core created during the scaffolding. Correct me if I am wrong please.

    The above all works.

    My next task is to figure out how I can get some of the Transaction foreign relationship to resolve.

    Created a ProviderTransaction model that lives in the Model folder in BtApiCore project, alongside with the Entity models.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace BtApiCore.Model
    {
        public class ProviderTransaction
        {
            [Key] public int TransactionId { get; set; }
    
            public string Location { get; set; }
    
            public string OName { get; set; }
    
            public string State { get; set; }
    
            public string CName { get; set; }
    
            public int BillNo { get; set; }
    
            public bool IsBilled { get; set; }
            public string Service { get; set; }
            public decimal Charge { get; set; }
            public decimal Tax { get; set; }
            public DateTime TDate { get; set; }
            public DateTime BDate { get; set; }
            public bool IsPaid { get; set; }
    
            public virtual Client Client { get; set; }
            public virtual LocationTxRate Ltr { get; set; }
            [ForeignKey("OwnerBillToId")]
            public virtual Owner OwnerBillTo { get; set; }
            [ForeignKey("OwnerLocationId")]
            public virtual Owner OwnerLocation { get; set; }
            public virtual Property Property { get; set; }
            public virtual Provider Provider { get; set; }
            public virtual ServiceLevel Sl { get; set; }
        }
    }
    
    public DbSet<ProviderTransaction> ProviderTransactions { get; set; }
    [HttpGet]
            public async Task<ActionResult<List<ProviderTransaction>>> Get() => await context.ProviderTransactions
                .OrderByDescending(t => t.TransactionId)
                .ToListAsync();
    BtServer.ProviderTransaction[] providertransactions;
    
        protected async override Task OnInitializedAsync()
        {
            var httpClient = ClientFactory.CreateClient("ServerApi");
            httpClient.BaseAddress = new Uri(@"https://localhost:44317/");
            httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    
            providertransactions = await httpClient.GetFromJsonAsync<BtServer.ProviderTransaction[]>("api/ProviderTransaction");
        }

    I am thinking this should now work. :(  Nope, problem with the API, below is the HttpRepl output. I am assuming it doesn't like context.ProviderTransaction highlighted yellow above.

    https://localhost:44317/api> dir
    .                     []
    ..                    []
    Breed                 [GET]
    Client                [GET]
    Country               [GET]
    Owner                 [GET]
    Printer               [GET]
    Provider              [GET]
    ProviderTransaction   [GET]
    Transaction           [GET]
    User                  [GET]
    
    https://localhost:44317/api> Get ProviderTransaction
    HTTP/1.1 500 Internal Server Error
    Content-Type: text/plain
    Date: Wed, 30 Dec 2020 17:10:26 GMT
    Server: Microsoft-IIS/10.0
    Transfer-Encoding: chunked
    X-Powered-By: ASP.NET
    
    Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid object name 'ProviderTransactions'.
       at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__169_0(Task`1 result)
       at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
       at System.Threading.Tasks.Task.<>c.<.cctor>b__277_0(Object obj)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
    --- End of stack trace from previous location ---
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
    --- End of stack trace from previous location ---
       at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
       at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
       at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
       at BtApiCore.Controllers.ProviderTransactionController.Get() in C:\Users\Robert\source\Repos\BtApiCore\Controllers\ProviderTransactionController.cs:line 25
       at lambda_method5(Closure , Object )
       at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
       at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
       at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
       at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
       at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
       at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
    ClientConnectionId:9e77a8b9-f5e0-48c2-8229-2c01519905aa
    Error Number:208,State:1,Class:16
    
    HEADERS
    =======
    Host: localhost:44317
    User-Agent: HTTP-REPL

    Help me understand how this is supposed to work, please.

    Wednesday, December 30, 2020 5:15 PM

Answers