英文:
How to fetch a second API based on the response of a first API?
问题
I don't understand why my C# code isn't working.
Basically I want to fetch a URL, and once I get the response I want to use that response and fetch another URL.
For this, I have two methods:
TestSuiteModel TestSuites;
public async Task GetTestSuites()
{
string url = "https://dev.azure.com/XXX/_apis/test/Plans/12/suites?api-version=5.0";
TestSuites = await TestSuiteService.GetTestSuites(url);
if (TestSuites != null)
{
foreach (var ts in TestSuites.value)
{
await this.GetTestCasess(ts.url);
}
}
}
TestCasesModel TestCases;
private async Task GetTestCasess(string url)
{
TestCases = await TestCasesService.GetTestCases(url);
}
and then I try to render the result like this:
@if (TestSuites != null)
{
-
@foreach (var ts in TestSuites.value)
- @ts.name
{
}
}
@if (TestCases.value != null)
{
-
@foreach (var ts in TestCases.value)
- @ts.testCase.webUrl
{
}
}
The first foreach works, but the second one throws this error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
TestCases was null.
It is always the same error no matter how I rewrite the logic.
The second URL has no issues.
Basically, there are no issues with the URLs, Models, Services. The problem has something to do with async/await that I haven't figured out yet.
For context, this is how I am calling my Models, Services, and OnInitializedAsync:
@page "/";
@using BlazorTest.Models.TestSuiteModel;
@using BlazorTest.Models.TestCasesModel;
@inject BlazorTest.Services.TestSuiteService TestSuiteService;
@inject BlazorTest.Services.TestCasesService TestCasesService;
protected override async Task OnInitializedAsync()
{
await this.GetTestSuites();
await base.OnInitializedAsync();
}
英文:
I don't understand why my C# code isn't working.
Basically I want to fetch a URL, and once I get the response I want to use that reponse and fetch another URL.
For this, I have two methods:
TestSuiteModel TestSuites;
public async Task GetTestSuites()
{
string url = "https://dev.azure.com/XXX/_apis/test/Plans/12/suites?api-version=5.0";
TestSuites = await TestSuiteService.GetTestSuites(url);
if(TestSuites != null)
{
foreach (var ts in TestSuites.value)
{
await this.GetTestCasess(ts.url);
}
}
}
TestCasesModel TestCases;
private async Task GetTestCasess(string url)
{
TestCases = await TestCasesService.GetTestCases(url);
}
and then I try to render the result like this:
@if(TestSuites != null)
{
<ul>
@foreach (var ts in TestSuites.value)
{
<li> @ts.name </li>
}
</ul>
}
@if (TestCases.value != null)
{
<ul>
@foreach (var ts in TestCases.value)
{
<li> @ts.testCase.webUrl </li>
}
</ul>
}
The first foreach works, but the second one throws this error:
> System.NullReferenceException: 'Object reference not set to an
> instance of an object.'
>
> TestCases was null.
It is always the same error no matter how re-write the logic.
The second URL has no issues.
Basically there is no issues with the URLs, Models, Services. The problem has something to do with async/await I haven't figured out yet.
For context, this is how I am calling my Models, Services and OnInitializedAsync
@page "/";
@using BlazorTest.Models.TestSuiteModel;
@using BlazorTest.Models.TestCasesModel;
@inject BlazorTest.Services.TestSuiteService TestSuiteService;
@inject BlazorTest.Services.TestCasesService TestCasesService;
protected override async Task OnInitializedAsync()
{
await this.GetTestSuites();
await base.OnInitializedAsync();
}
答案1
得分: 1
我假设错误与任何请求或特定逻辑无关。
错误消息是:
System.NullReferenceException: '未将对象引用设置到对象的实例。'
TestCases为null。
它表示TestCases
的值为空。
我在你的代码中看到了这一行:
@if (TestCases.value != null)
你应该将它改为(注意 ?
):
@if (TestCases?.value != null)
它会检查TestCases
是否不为空,或者TestCases.value
是否不为空。
?.
– 一个空值条件运算符,只有在其操作数评估为非空时才对其进行成员访问操作;否则,它返回 null
英文:
> I assume, the error is not relevant to any requests or specific logic
Error message is:
> System.NullReferenceException: 'Object reference not set to an instance of an object.'
>
> TestCases was null.
It says: value of the TestCases
is null.
It means that you are trying to do something with value of TestCases
.
I see this line in your code:
> @if (TestCases.value != null)
You should change it to (notice the ?
):
> @if (TestCases?.value != null)
It will check if TestCases
is not null
or TestCases.value
is not null
.
> ?.
– a null-conditional operator applies a member access operation to its operand only if that operand evaluates to non-null; otherwise, it returns null
>
> https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-
答案2
得分: 1
@Vlad DX 是正确的。
原因是因为第一个异步调用会将线程控制返回给组件代码,从而触发渲染事件。在这一点上,`TestCases` 是空的。
以下是您问题的最小复现代码示例。
我假设您要么在项目中禁用了 `Nullable`,要么忽略了警告???
英文:
@Vlad DX is correct.
The reason is because the first async call yields thread control back to Component code which runs a render event. At which point TestCases
is null.
Here's a minimum reproduction code sample of your issue.
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
@if(TestSuiteModel is not null)
{
<div>display</div>
}
@*Will Work*@
@*@if (TestCaseModel?.Value is not null)
{
<div>display</div>
}
*@
@if (TestCaseModel.Value is not null)
{
<div>display</div>
}
@code {
TestSuite? TestSuiteModel;
TestCase? TestCaseModel;
protected async override Task OnInitializedAsync()
=> await GetData();
private async ValueTask GetData()
{
// fake an async call to an API/Db
await Task.Delay(1000);
// First render of the component occurs here
TestSuiteModel = new(Enumerable.Empty<string>());
// fake an async call to an API/Db
await Task.Delay(1000);
TestCaseModel = new(Enumerable.Empty<string>());
}
public record TestSuite(IEnumerable<string> Value);
public record TestCase(IEnumerable<string> Value);
}
I'm assuming you either have Nullable
disabled on the project or are ignoring the warnings???
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论