为什么这个 Blazor WebAssembly api Get 函数不起作用?
Why doesn't this Blazor WebAssembly api Get function work?
我有一个 Blazor WASM 应用程序,我正在修改模板 weatherforecastcontroller 以添加一个 Get,我可以在其中传递一个 id:
[HttpGet("{userId}")]
public string Get(string userId)
{
return userId;
}
在调用它的组件上:
protected override async Task OnInitializedAsync()
{
var id = await Http.GetFromJsonAsync<WeatherForecast>("WeatherForecast/1);
}
但抛出错误:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: The provided ContentType is not supported; the supported types are 'application/json' and the structured syntax suffix 'application/+json'.
System.NotSupportedException: The provided ContentType is not supported; the supported types are 'application/json' and the structured syntax suffix 'application/+json'.
at System.Net.Http.Json.HttpContentJsonExtensions.ValidateContent (System.Net.Http.HttpContent content) <0x2f6ff90 + 0x0009a> in <filename unknown>:0
怎么了?如果我手动输入地址栏:
http://localhost:59728/weatherforecast/1
...我得到了我期望的 ID。
这个:
Http.GetFromJsonAsync<WeatherForecast>
应该是
Http.GetFromJsonAsync<string>
换句话说,指示 json 序列化器从 HTTP 调用中期望什么类型的类型说明符是字符串,而不是 class、WeatherForecast
更新:
@page "/"
@inject HttpClient Http
<h1>@output</h1>
@code
{
private string output;
protected override async Task OnInitializedAsync()
{
var val = "1";
output = await Http.GetFromJsonAsync<string>($"WeatherForecast?value={val}");
}
}
WeatherForecastController.cs
[HttpGet]
public string Get(string value)
{
return value;
}
Startup.ConfigureServices方法
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options =>
{
options.OutputFormatters.RemoveType<StringOutputFormatter>();
});
services.AddRazorPages();
}
注意:也可以添加Produces
属性来指定响应类型格式,像这样:
[HttpGet]
[Produces("application/json")]
public string Get(string value)
{
return value;
}
你也应该改变
services.AddControllersWithViews(options =>
{
options.OutputFormatters.RemoveType<StringOutputFormatter>();
});
到
services.AddControllersWithViews();
你说直接调用API就可以了,但是返回的是1
还是"1"
?这很重要,因为只有后者有效 JSON。由于您要求 JSON (GetFromJsonAsync
),因此原始值 1
会导致问题。作为 the docs state:
By default, string return types are formatted as text/plain
您可以查看文档以了解可能的解决方案。这是一个片段:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// Removes the special case for strings
options.OutputFormatters.RemoveType<StringOutputFormatter>();
});
其他选项包括手动返回 HttpResponseMessage
以及在 StringContent
.
的实例中指定的字符串值
注意:enet也是对的,需要把WeatherForecast
改成string
。
除了@enet 建议的修复之外,您的控制器也存在问题。当您 return 一个 string
时,Content-Type
被设置为 text/plain
并且您的 HTTP 客户端期望 JSON。这是一个例子:
[HttpGet("text")]
public string GetText()
{
return "Hello, this is text/plain";
}
[HttpGet("maybe-json")]
public ActionResult<string> GetMaybeJson()
{
return Ok("Hello, this is still text/plain.");
}
// ** THIS SHOULD WORK **
[HttpGet("json")]
public ActionResult<string> GetJson()
{
return new JsonResult("Hello, this is application/json");
}
同样,如果您使用端点 returning WeatherForecast
进行了测试,那么 Content-Type
将是 application/json
并且您的 Blazor 代码将起作用。您应该能够在您的控制器中尝试 GetJson()
并查看您的代码工作。
[HttpGet("{userId}")]
public string Get(string userId)
{
return userId;
}
在调用它的组件上:
protected override async Task OnInitializedAsync()
{
var id = await Http.GetFromJsonAsync<WeatherForecast>("WeatherForecast/1);
}
但抛出错误:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: The provided ContentType is not supported; the supported types are 'application/json' and the structured syntax suffix 'application/+json'.
System.NotSupportedException: The provided ContentType is not supported; the supported types are 'application/json' and the structured syntax suffix 'application/+json'.
at System.Net.Http.Json.HttpContentJsonExtensions.ValidateContent (System.Net.Http.HttpContent content) <0x2f6ff90 + 0x0009a> in <filename unknown>:0
怎么了?如果我手动输入地址栏:
http://localhost:59728/weatherforecast/1
...我得到了我期望的 ID。
这个:
Http.GetFromJsonAsync<WeatherForecast>
应该是
Http.GetFromJsonAsync<string>
换句话说,指示 json 序列化器从 HTTP 调用中期望什么类型的类型说明符是字符串,而不是 class、WeatherForecast
更新:
@page "/"
@inject HttpClient Http
<h1>@output</h1>
@code
{
private string output;
protected override async Task OnInitializedAsync()
{
var val = "1";
output = await Http.GetFromJsonAsync<string>($"WeatherForecast?value={val}");
}
}
WeatherForecastController.cs
[HttpGet]
public string Get(string value)
{
return value;
}
Startup.ConfigureServices方法
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options =>
{
options.OutputFormatters.RemoveType<StringOutputFormatter>();
});
services.AddRazorPages();
}
注意:也可以添加Produces
属性来指定响应类型格式,像这样:
[HttpGet]
[Produces("application/json")]
public string Get(string value)
{
return value;
}
你也应该改变
services.AddControllersWithViews(options =>
{
options.OutputFormatters.RemoveType<StringOutputFormatter>();
});
到
services.AddControllersWithViews();
你说直接调用API就可以了,但是返回的是1
还是"1"
?这很重要,因为只有后者有效 JSON。由于您要求 JSON (GetFromJsonAsync
),因此原始值 1
会导致问题。作为 the docs state:
By default, string return types are formatted as text/plain
您可以查看文档以了解可能的解决方案。这是一个片段:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// Removes the special case for strings
options.OutputFormatters.RemoveType<StringOutputFormatter>();
});
其他选项包括手动返回 HttpResponseMessage
以及在 StringContent
.
注意:enet也是对的,需要把WeatherForecast
改成string
。
除了@enet 建议的修复之外,您的控制器也存在问题。当您 return 一个 string
时,Content-Type
被设置为 text/plain
并且您的 HTTP 客户端期望 JSON。这是一个例子:
[HttpGet("text")]
public string GetText()
{
return "Hello, this is text/plain";
}
[HttpGet("maybe-json")]
public ActionResult<string> GetMaybeJson()
{
return Ok("Hello, this is still text/plain.");
}
// ** THIS SHOULD WORK **
[HttpGet("json")]
public ActionResult<string> GetJson()
{
return new JsonResult("Hello, this is application/json");
}
同样,如果您使用端点 returning WeatherForecast
进行了测试,那么 Content-Type
将是 application/json
并且您的 Blazor 代码将起作用。您应该能够在您的控制器中尝试 GetJson()
并查看您的代码工作。