变量未分配给从 C# 中的 URL 获取的结果

ele*_*tra 1 c# blazor

我遇到这个问题已经有一段时间了,为了重现该错误,我创建了一个新的 Blazor 项目来向您显示所有文件。

这是我的index.razor文件:

@using BlazorApp1.Models.TestSuiteModel; 
@inject BlazorApp1.Services.TestSuiteService TestSuiteServ; 
@page "/"


<b> 

    @TestSuitesResult.count; 

</b>



@code {

    protected override async Task OnInitializedAsync()
    {

        this.GetTestSuites(); 
    }


    TestSuiteModel TestSuitesResult;
    protected async Task GetTestSuites()
    {
        TestSuiteServ.url = "https://dev.azure.com/****/_apis/test/Plans/12/suites?api-version=5.0";
        TestSuiteServ.PersonalAccessToken = "****";
        TestSuitesResult = await TestSuiteServ.GetTestSuites();
        await base.OnInitializedAsync();

    }

}
Run Code Online (Sandbox Code Playgroud)

问题是@TestSuitesResult.count;始终为空并引发此错误: 在此输入图像描述

下面是我的模型

namespace BlazorApp1.Models.TestSuiteModel
{
    public class TestSuiteModel
    {
        public List<Value> value { get; set; }
        public int count { get; set; }
    }
 // .. mode classes
}
Run Code Online (Sandbox Code Playgroud)

以下是我的服务

using BlazorApp1.Models.TestSuiteModel;
using Newtonsoft.Json;
using System.Net.Http.Headers;

using System.Net.Http.Headers;

namespace BlazorApp1.Services
{
    public class TestSuiteService
    {
        public string url { get; set; }
        public string PersonalAccessToken { get; set; }
        TestSuiteModel result;

        public async Task<TestSuiteModel> GetTestSuites()
        {
            using (HttpClient client = new HttpClient())
            {
                // accept response as JSON
                client.DefaultRequestHeaders.Accept.Add(
                    new MediaTypeWithQualityHeaderValue("application/json")
                );

                // add DevOps token to the HTTP Header request
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                    "Basic", Convert.ToBase64String(
                        System.Text.Encoding.ASCII.GetBytes(
                            string.Format("{0}:{1}", "", PersonalAccessToken)
                        )
                    )
                );


                HttpResponseMessage response = await client.GetAsync(url);
                response.EnsureSuccessStatusCode();
                string responseData = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<TestSuiteModel>(responseData);

            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在这个项目中唯一拥有的东西。除了在中注册服务之外,我没有修改或删除默认 Blazor 项目中的任何文件program.cs

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddSingleton<TestSuiteService>(); <!-- my service -->

var app = builder.Build();
Run Code Online (Sandbox Code Playgroud)

还添加了 Newtonsoft,因此它不可能是缺少的库。

Pan*_*vos 7

GetTestSuites永远不会被等待

protected override async Task OnInitializedAsync()
{

    this.GetTestSuites(); 
}
Run Code Online (Sandbox Code Playgroud)

它应该是 :

protected override async Task OnInitializedAsync()
{

    await this.GetTestSuites(); 
}
Run Code Online (Sandbox Code Playgroud)

现在已OnInitializedAsync完成,并且页面在GetTestSuites有机会完成之前呈现。

还有其他问题TestSuiteService。HttpClient 旨在重用,而不是在using块中定义。特别是在 Blazor 中,HttpClient 实例是由浏览器提供的。整个GetTestSuites方法可以替换为单个方法await _httpClient.GetFromJsonAsync<TestSuiteModel>(url);,其中_httpClient可以是通过 注册的 HttpClient AddHttpClient其他一切都是GetFromJsonAsync的默认行为:

public interface ITestSuiteService
{
    Task<TestSuiteModel> GetTestSuites(string url);
}

public class TestSuiteService:ITestSuiteService
{
    public TestSuiteService(HttpClient client)
    {
        _httpClient=client;
    }

    public async Task<TestSuiteModel> GetTestSuites(string url)
    {
        var model=await _httpClient.GetFromJsonAsync<TestSuiteModel>(url);
        return model;
    }
}
Run Code Online (Sandbox Code Playgroud)

该服务可以注册为类型化的 HttpClient :

builder.Services.AddHttpClient<ITestSuiteService,TestSuiteService>(client=>{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Basic", Convert.ToBase64String(
                    System.Text.Encoding.ASCII.GetBytes(
                        $":{PersonalAccessToken}")
                    )
                )
            );
});
Run Code Online (Sandbox Code Playgroud)

此时可以从配置中检索令牌。

另一种选择是使用GetAsyn、检查响应并使用HttpContent.ReadFromJsonAsync。这避免了异常的成本,特别是在 API 中,当需要像 429(请求过多)这样的响应时:

    public async Task<TestSuiteModel> GetTestSuites(string url)
    {
        var response=await _httpClient.GetAsync(url);
        if(response.IsSuccessStatusCode)
        {
            var model=await response.Content.ReadFromJsonAsync<TestSuiteModel>();
            return model;
        }
        else 
        {
        ...
        }
    }
Run Code Online (Sandbox Code Playgroud)


Mar*_*ein 5

对象的初始状态为 null。

您必须在此处进行空检查或提供默认对象。您可以通过三种方法来解决此问题。1:使用 if 检查 null

<b> 
@if(TestSuitesResult is not null)
{
    @TestSuitesResult.count; 
}
</b>
Run Code Online (Sandbox Code Playgroud)

2:使用 Elvis 运算符检查 null

<b> 
    @TestSuitesResult?.count; 
</b>
Run Code Online (Sandbox Code Playgroud)

3:提供默认值

TestSuiteModel TestSuitesResult = new TestSuiteModel();
Run Code Online (Sandbox Code Playgroud)

还要确保等待您的函数,OnInitializedAsync否则您将调用您的函数并忘记它。