How to retrieve data from a service class in Blazor Server App(.NET 5)?

Viewed 43

I am currently stuck with a problem regarding Blazor(.NET 5).

As of now, I have two service classes for two entities(User and Role), both of them have their own table in the DB.

I have made a razor component for creating a new User and on initialization it gets all the of the roles from the DB and stores them in a IEnumerable variable.

However, every time I open the AddUser component in the browser, I get a 500 error("Failed to load resource: the server responded with a status of 500 ()") and the IEnumerable variable is null.

I tested the controller classes for both Role and User in SwaggerUI and they work, so I know for a fact it is a problem with either the UserService/RoleService or maybe its a problem with my Startup.cs.

Dose anybody know why is it not working?

Startup.cs(Blazor Server App)

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddSingleton<WeatherForecastService>();
            services.AddScoped<UserService>();
            services.AddScoped<RoleService>();
            services.AddHttpClient();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }

UserService

public class UserService
    {
        private readonly HttpClient _httpClient;
        private readonly string BaseApiUrl = "https://localhost:44340/api/User";
        public UserService(HttpClient httpClient) => _httpClient = httpClient;
        public async Task<List<User>> GetUsers()
        {
            return await _httpClient.GetFromJsonAsync<List<User>>(BaseApiUrl);
        }
        public async Task AddUserAsync(User user)
        {
            var request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl);
            request.Content = new StringContent(JsonSerializer.Serialize(user), Encoding.UTF8, "application/json");
            await _httpClient.SendAsync(request);
        }
        public async Task<User> GetUserAsync(int userId)
        {
            return await _httpClient.GetFromJsonAsync<User>($"{BaseApiUrl}/{userId}");
        }
        public async Task UpdateUserAsync(User user)
        {
            var request = new HttpRequestMessage(HttpMethod.Put, BaseApiUrl);
            request.Content = new StringContent(JsonSerializer.Serialize(user), Encoding.UTF8, "application/json");
            await _httpClient.SendAsync(request);
        }
        public async Task DeleteUserAsync(int userId)
        {
            var httpRequest = new HttpRequestMessage(HttpMethod.Delete, $"{BaseApiUrl}/{userId}");
            await _httpClient.SendAsync(httpRequest);
        }
    }

RoleService

public class RoleService
    {
        private readonly HttpClient _httpClient;
        private readonly string BaseApiUrl = "https://localhost:44340/api/Role";
        public RoleService(HttpClient httpClient) => _httpClient = httpClient;
        public Task<List<Role>> GetRoles()
        {
            return _httpClient.GetFromJsonAsync<List<Role>>(BaseApiUrl);
        }
        public Task<Role> GetRoleAsync(int roleId)
        {
            return _httpClient.GetFromJsonAsync<Role>($"{BaseApiUrl}/{roleId}");
        }
    }

UserFields

@using Domain.Entities
@using Radzen.Blazor
@using Backend.Services

@inject RoleService _roleService;

@if(roles == null)
{
    <div>Loading........</div>
}
else
{
    <div class="userFields">
     <label for="firstName">First Name</label>
     <InputText id="firstName" class="form-control" @bind-Value="@user.Firstname"></InputText>

     <label for="lastName">Last Name</label>
     <InputText id="lastName" class="form-control" @bind-Value="@user.Lastname"></InputText>

     <label for="firstName">First Name</label>
     <InputText id="firstName" class="form-control" @bind-Value="@user.Firstname"></InputText>

     <label for="password">Passowrd</label>
     <InputText id="password" class="form-control" @bind-Value="@user.Password"></InputText>

     
</div>
}

@code {
    [Parameter]
    public User user { get; set; }

    IEnumerable<Role> roles;

    protected override async void OnInitialized()
    {
        roles = await _roleService.GetRoles();
    }

    void OnChangeRoles(object value, string name)
    {
        user.Role = (Role)value;
    }
}

1 Answers

I think you should consider implement Interfaces for both services, and given you are going to perform Http Calls, you should implement as Transient

    services.AddTransient<UserService>();
    services.AddTransient<RoleService>();
Related