skip to Main Content

This is a Blazer server app, and im having trouble getting the values from the Controller using a ApiService, where I call the api service method from a @code section of the Index.razor page.

Index.razor


@code {

    private List<SystemUser> systemUsers;
    private List<RegisterUserModel> registerUserModels = new List<RegisterUserModel>();
    private RegisterUserModel registerUserModel = null;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            systemUsers = await SystemUsersService.GetSystemUsers();

            if (systemUsers != null && systemUsers.Count > 0)
            {
                foreach (SystemUser systemUser in systemUsers)
                {
                    registerUserModel = new RegisterUserModel()
                    {
                        FirstName = systemUser.FirstName
                        ,
                        LastName = systemUser.LastName
                        ,
                        Email = systemUser.Email
                        ,
                        UserName = systemUser.UserName
                        ,
                        Password = systemUser.Password
                    };

                    registerUserModels.Add(registerUserModel);
                }
            }

        }
        catch (Exception exception)
        {
            Console.WriteLine("Error " + exception);
        }
    }

}

ApiServiceClass

    public class SystemUsersService 
    {
        private readonly IHttpClientFactory _clientFactory;

        public SystemUsersService(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }
        public async Task<List<SystemUser>> GetSystemUsers()
        {
            var result = new List<SystemUser>();

            try
            {
                var url = string.Format("https://localhost:44391/systemusers/get");

                var request = new HttpRequestMessage(HttpMethod.Get, url);
                request.Headers.Add("Accept", "application/json");

                var client = _clientFactory.CreateClient();

                var response = await client.SendAsync(request);


                if (response.IsSuccessStatusCode)
                {
                    var stringResponse = await response.Content.ReadAsStringAsync();

                    result = JsonSerializer.Deserialize<List<SystemUser>>(stringResponse,
                        new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
                }
                else
                {
                    result = Array.Empty<SystemUser>().ToList();
                }
            } catch (Exception exception)
            {
                throw exception;
            }

            return result;

        }
    }
}

Controller

namespace ServerWebAppForCW.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class SystemUserController : ControllerBase
    {   

        [HttpGet("/systemusers/get")]
        public async Task<IEnumerable<SystemUser>> GetAll()
        {
            var model = new List<SystemUser>();
            RegisterUserModel registerUserModel = new RegisterUserModel();

            model = await registerUserModel.GetSystemUsers();

            return model;
        }

        [HttpGet("/systemusers/create")]
        public async Task<Boolean> CreateSystemUser(RegisterUserModel registerUserModel)
        {
            return await registerUserModel.CreateSystemUser();
        }
    }
}

From the below line of the Service class, the response i get over here is a weird html doc sort of thing in the content, though the status code is 200, when debugging the SendAsync does not call the controller method ‘GetAll()’. So i dont know from where this call even gets the data.

var response = await client.SendAsync(request);

Here is the image

response-of-api-call

Moving on, an error get’s thrown in he below line

result = JsonSerializer.Deserialize<List<SystemUser>>(stringResponse,
        new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

Which kind of makes sense since JsonSerilizer is trying to deserialize a html response.

Exception error image

Exception-error-image

Error in text:

{"'<' is an invalid start of a value. Path: $ | LineNumber: 1 | BytePositionInLine: 0."}

So my question would be why am i getting this weird html response rather than the HttpClientFactory call not calling my controller’s api?

Hope someone could explain this situation.

Fyi my start up injection

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddSingleton<WeatherForecastService>();
            services.AddScoped<SystemUserService>();
            services.AddSingleton<SystemUsersService>();


            services.AddDbContext<AppDBContext>(item => item.UseSqlServer(Configuration.GetConnectionString("myconn")));
            services.AddHttpClient();
        }

2

Answers


  1. Chosen as BEST ANSWER

    I added this relevant code to my Startup.cs at the end of the ConfigureServices method

    services.AddMvc(options => options.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
    

    ConfigureServices:

            public void ConfigureServices(IServiceCollection services)
            {
                services.AddRazorPages();
                services.AddServerSideBlazor();
                services.AddSingleton<WeatherForecastService>();
                services.AddScoped<SystemUserService>();
    
                //This one AddMvc
                services.AddMvc(options => options.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
    
                services.AddDbContext<AppDBContext>(item => item.UseSqlServer(Configuration.GetConnectionString("myconn")));
                services.AddScoped<HttpClient>();
            }
    
    

    Also add this line to the Configure method of the Startup.cs class after the 'app.UseRouting();'.

    app.UseMvcWithDefaultRoute();
    
            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.UseMvcWithDefaultRoute();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapBlazorHub();
                    endpoints.MapFallbackToPage("/_Host");
                });
            }
    

  2. services.AddRazorPages()
    

    does not provide support for API.

    To provide API routing, use any of the following:

    services.AddMvc();
    services.AddControllers();
    services.AddControllersWithViews();
    

    AddControllers is the most minimal implementation that will support API.

    https://learn.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio#mvc-service-registration

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search