Home > Software design >  Not getting a valid json from controller Get
Not getting a valid json from controller Get

Time:12-02

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();
        }

CodePudding user response:

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://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio#mvc-service-registration

CodePudding user response:

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");
            });
        }
  • Related