【问题标题】:Retrieving data contained in a List using a controller causes an error使用控制器检索列表中包含的数据会导致错误
【发布时间】:2021-11-11 17:51:56
【问题描述】:

我对 Blazor 和 Web 应用程序非常陌生。我一直卡在这个错误上,似乎无法弄清楚是什么原因造成的。我觉得是控制器,但我似乎也不知道为什么。

Todo.razor

@inject HttpClient http;
@inject BlazorTodoApp.Client.Services.ITodoItemService todoItemService

<h3> Todo (@todos.Count()) </h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="@todo.isDone" />
            <input @bind="@todo.Title" />
        </li>
    }
</ul>

<input placeholder="something todo" @bind="newTodo" />
<button @onclick="AddTodo"> Add Todo</button>


@code {

private List<TodoItem> todos = new List<TodoItem>();
private string newTodo;

private void AddTodo()
{

    if (!string.IsNullOrWhiteSpace(newTodo)) {
        todos.Add(new TodoItem { Title = newTodo });
        newTodo = string.Empty;
    }
}

protected override async Task OnInitializedAsync()
{
    try
    {
        todos = await http.GetFromJsonAsync<List<TodoItem>>("api/TodoItems");
    }
    catch (AccessTokenNotAvailableException exception)
    {
        exception.Redirect();
    }
}

控制器

public class TodoItemsController : ControllerBase
{

    public List<TodoItem> todoPosts { get; set; } = new List<TodoItem>()
    {
        new TodoItem {Id = 1, Title = "number 11:",  isDone = false},
        new TodoItem {Id = 2, Title = "number 21:",  isDone = false}
    };

    [HttpGet]
    public ActionResult<List<TodoItem>> GetItems()
    {

        return Ok(todoPosts);
    }
}

错误

单击 HTTP 请求链接会显示我的数据,但它没有显示为页面 HTML 部分中的编码

HTML

调整了待办事项标题,使其旁边显示“待办事项”列表的大小,并且由于某种原因它保持为 0。

要求的课程

Program.cs [客户端]

 public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("#app");

        builder.Services.AddHttpClient("BlazorTodoApp.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
            .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

        // Supply HttpClient instances that include access tokens when making requests to the server project
        builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("BlazorTodoApp.ServerAPI"));
        //builder.Services.AddScoped<ITodoItemService, TodoItemService>();
        builder.Services.AddMsalAuthentication(options =>
        {
            builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
            options.ProviderOptions.DefaultAccessTokenScopes.Add("api://api.id.uri/access_as_user");
        });

        await builder.Build().RunAsync();
    }
}

Startup.cs [服务器]

    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.AddDbContext<DataContext>(x => x.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));

        services.AddControllersWithViews();
        services.AddRazorPages();
    }

    // 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();
            app.UseWebAssemblyDebugging();
        }
        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.UseBlazorFrameworkFiles();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("index.html");
        });
    }
}

【问题讨论】:

  • 好像没有初始化HttpClient对象
  • 错误提示为TodoItemService.cs:line 30,但您只向我们展示了其中的 15 行。第 30 行是什么?
  • 第 30 行:返回等待 _http.GetFromJsonAsync>("api/TodoItems");。我删除了上面的一些方法,因此在帖子中更清晰,减少了行数。
  • 您的控制器看起来不错。您正在初始化 todoPosts,因此这不会是“未设置对象实例的对象引用”。在 TodoItemService 类的构造函数的开头放置一个断点,以确保 http(不是 _http)您已经在 Startup.cs 中正确注册了服务并且它不为空。在 Todo.razor 中有很多问题可能是您的问题的根源。可能是您的应用程序在您的 foreach 循环中产生了一个空的 todo 项。您绑定的 newTodo 和 AddTodo 的代码是什么样的?总而言之,我们需要更多信息来提供帮助。
  • 您从对@todos.Count() 的调用中获得计数的事实告诉我们您的待办事项列表不为空。否则,UI 不会在您的屏幕截图中呈现默认页面。

标签: c# blazor blazor-webassembly


【解决方案1】:

这里有一些提示可以尝试:

  1. 确认控制器被击中并重构代码以确保它返回您期望的内容。

  2. GetFromJsonAsync 替换为GetAsync,看看你会得到什么回复。检查响应和返回的对象。

每个人都在进行有根据的猜测。您需要通过在调试模式下逐行执行代码来确定未将哪个对象引用设置为实例。

【讨论】:

    【解决方案2】:

    从错误消息看来,ITodoItemService 需要正确注入系统。

    【讨论】:

    • 否定,你会得到一个开发者错误页面,说明服务丢失。
    猜你喜欢
    • 2016-03-30
    • 2013-07-24
    • 1970-01-01
    • 2016-01-11
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多