为什么我在 GET 请求中得到 Unsupported Media Type? (.NET 6)
Why I get Unsuported Media Type on GET request? (.NET 6)
我肯定遗漏了什么,因为大多数关于 415 错误的问题都涉及 POST 请求。
在这种情况下,这是一个非常简单的 GET 请求,当我枚举所有操作参数时它会起作用,但如果我创建一个简单的 DTO 来包含所有这些,我将开始收到 415 错误。
我正在使用 https://localhost:555/some/test?field1=aaa&field2=1
调用 api
这个有效:
[ApiController]
public class SomeController : ControllerBase
{
[Route("Test")]
public SomeResponse GetSomeResponse(string field1, int field2)
{
return new SomeResponse(field1, field2);
}
}
但事实并非如此:
[ApiController]
public class SomeController : ControllerBase
{
[Route("Test")]
public SomeResponse GetSomeResponse(SomeRequest request)
{
return new SomeResponse(request.Field1, request.Field2);
}
}
public class SomeRequest
{
public string Field1 { get; set; }
public int Field2 { get; set; }
}
public class SomeResponse
{
public Someresponse(string field1, int field2)
{
Field1 = field1;
Field2 = field2;
}
public string Field1 { get; set; }
public int Field2 { get; set; }
}
控制器 class 仅使用 Microsoft.AspNetCore.Mvc;
当我尝试使用 SomeRequest class 时,API 回答“415 - 不受支持的媒体类型”
唯一的区别是接收值的方式,我不会从 uri 切换到正文(可能是 json 或纯文本等)
但是因为我没有使用正文,所以我无法理解它指的是哪种媒体类型
我的启动class与WeatherForecast相同,使用项目模板ASP.NET Core Web API创建,Visual Studio 2022,.Net6
Ben Foster 在 Custom Model Binding in ASP.NET 6.0 Minimal APIs
中对此有一篇很棒的文章
我自己还没有尝试过,但是将此 TryParse
方法添加到您的 SomeRequest
类型可能会有所帮助:
static bool TryParse(string? value, IFormatProvider? provider, out T parameter)
通常我尽量不将对象绑定到 HttpGet
,因为标准对象序列化使用在标准 URL 路由中具有其他含义的字符,因此需要在 url 中进行转义,这只会使服务器和客户端实现变得过于复杂。
我支持像 Point
这样的常见复杂类型样式结构的概念,认为您可以在许多控制器和端点中重复使用它,但是为每个请求创建一个对象包装器将是可笑的,那是生成的客户端中常见的客户端技术,但我们尽量避免在服务器端使用。
我建议不要将对象绑定为 GET 参数,因为它是一种非标准的代码风格,在 API 管理和客户端实现方面都会给解决方案带来一定程度的技术债务。
即使您使用自定义绑定器或路由处理程序,这些解决方案最终也会成为比使用原始参数并将它们映射到端点方法第一行中的首选类型实现更多的自定义代码。
嗯,一个可能的解决方案是指定 [FromQuery]:
public SomeResponse GetSomeResponse([FromQuery] SomeRequest request)
不过,作为对“不受支持的格式”的反应,我对此不是很满意,因此,欢迎提出其他建议。
您应该使用 HttpGetAttribute
将请求绑定到查询字符串参数并专门限定请求范围,以便仅允许 GET
:
[HttpGet("Test")]
public SomeResponse GetSomeResponse2(SomeRequest request)
{
return new SomeResponse(request.Field1, request.Field2);
}
这很微妙,但自从 .Net 5(当 FromUriAttribute 被替换并且各种 OData 和 MVC 路由机制被组合到一个公共管道中时)我们被鼓励使用 HttpGetAttribute
(或其他 Http Method 变体)而不是 RouteAttribute
作为最小化配置的方法。
此代码具有与 类似的功能,但它会阻止用户尝试使用 POST
访问此端点。 [FromQuery]
创建一个控制器,即使 JSON 对象被 POST
ed 到端点,参数也专门映射到查询参数。
我肯定遗漏了什么,因为大多数关于 415 错误的问题都涉及 POST 请求。 在这种情况下,这是一个非常简单的 GET 请求,当我枚举所有操作参数时它会起作用,但如果我创建一个简单的 DTO 来包含所有这些,我将开始收到 415 错误。
我正在使用 https://localhost:555/some/test?field1=aaa&field2=1
调用 api这个有效:
[ApiController]
public class SomeController : ControllerBase
{
[Route("Test")]
public SomeResponse GetSomeResponse(string field1, int field2)
{
return new SomeResponse(field1, field2);
}
}
但事实并非如此:
[ApiController]
public class SomeController : ControllerBase
{
[Route("Test")]
public SomeResponse GetSomeResponse(SomeRequest request)
{
return new SomeResponse(request.Field1, request.Field2);
}
}
public class SomeRequest
{
public string Field1 { get; set; }
public int Field2 { get; set; }
}
public class SomeResponse
{
public Someresponse(string field1, int field2)
{
Field1 = field1;
Field2 = field2;
}
public string Field1 { get; set; }
public int Field2 { get; set; }
}
控制器 class 仅使用 Microsoft.AspNetCore.Mvc;
当我尝试使用 SomeRequest class 时,API 回答“415 - 不受支持的媒体类型”
唯一的区别是接收值的方式,我不会从 uri 切换到正文(可能是 json 或纯文本等) 但是因为我没有使用正文,所以我无法理解它指的是哪种媒体类型
我的启动class与WeatherForecast相同,使用项目模板ASP.NET Core Web API创建,Visual Studio 2022,.Net6
Ben Foster 在 Custom Model Binding in ASP.NET 6.0 Minimal APIs
中对此有一篇很棒的文章我自己还没有尝试过,但是将此 TryParse
方法添加到您的 SomeRequest
类型可能会有所帮助:
static bool TryParse(string? value, IFormatProvider? provider, out T parameter)
通常我尽量不将对象绑定到 HttpGet
,因为标准对象序列化使用在标准 URL 路由中具有其他含义的字符,因此需要在 url 中进行转义,这只会使服务器和客户端实现变得过于复杂。
我支持像 Point
这样的常见复杂类型样式结构的概念,认为您可以在许多控制器和端点中重复使用它,但是为每个请求创建一个对象包装器将是可笑的,那是生成的客户端中常见的客户端技术,但我们尽量避免在服务器端使用。
我建议不要将对象绑定为 GET 参数,因为它是一种非标准的代码风格,在 API 管理和客户端实现方面都会给解决方案带来一定程度的技术债务。
即使您使用自定义绑定器或路由处理程序,这些解决方案最终也会成为比使用原始参数并将它们映射到端点方法第一行中的首选类型实现更多的自定义代码。
嗯,一个可能的解决方案是指定 [FromQuery]:
public SomeResponse GetSomeResponse([FromQuery] SomeRequest request)
不过,作为对“不受支持的格式”的反应,我对此不是很满意,因此,欢迎提出其他建议。
您应该使用 HttpGetAttribute
将请求绑定到查询字符串参数并专门限定请求范围,以便仅允许 GET
:
[HttpGet("Test")]
public SomeResponse GetSomeResponse2(SomeRequest request)
{
return new SomeResponse(request.Field1, request.Field2);
}
这很微妙,但自从 .Net 5(当 FromUriAttribute 被替换并且各种 OData 和 MVC 路由机制被组合到一个公共管道中时)我们被鼓励使用 HttpGetAttribute
(或其他 Http Method 变体)而不是 RouteAttribute
作为最小化配置的方法。
此代码具有与 POST
访问此端点。 [FromQuery]
创建一个控制器,即使 JSON 对象被 POST
ed 到端点,参数也专门映射到查询参数。