我面临一个奇怪的问题,几乎花了4个小时没有运气。
我有一个简单的Web API,可以在表单提交时调用。
API-
// POST: api/Tool
[HttpPost]
public void Post([FromBody] Object value)
{
_toolService.CreateToolDetail(Convert.ToString(value));
}
HTML-
<!DOCTYPE html>
<html>
<body>
<h2>HTML Forms</h2>
<form name="value" action="https://localhost:44352/api/tool" method="post">
First name:<br>
<input type="text" id="PropertyA" name="PropertyA" value="Some value A">
<br>
Last name:<br>
<input type="text" id="PropertyB" name="PropertyB" value="Some value B">
<br><br>
<!--<input type="file" id="Files" name="Files" multiple="multiple"/>-->
<br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
当我点击“提交”按钮时,我得到以下错误-
{"":["The input was not valid."]}
启动类中的配置-
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSingleton<IConfiguration>(Configuration);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
}
这仅在POST请求中发生。 GET请求工作正常。在Postman REST客户端中进行测试时,存在相同的问题。有什么帮助吗?如果可以提供更多详细信息,请告诉我。
答案 0 :(得分:25)
请勿使用FromBody
。您以x-www-form-urlencoded
的身份提交(即标准HTML表单发布)。 FromBody
属性用于JSON / XML。
您无法通过同一操作处理标准表单提交和 JSON / XML请求正文。如果您需要两种方式都请求操作,则需要两个单独的端点,一个端点的参数用FromBody
装饰,另一个端点不带。没有别的办法了。您可以将操作的实际功能分解为两个操作都可以使用的私有方法,以减少代码重复。
答案 1 :(得分:10)
我只是在这里经历了类似的情况。我可以毫无问题地使用[FromBody]:
public class MyController : Controller
{
[HttpPost]
public async Task<IActionResult> SomeEndpoint([FromBody]Payload inPayload)
{
...
}
}
public class Payload
{
public string SomeString { get; set; }
public int SomeInt { get; set; }
}
我发现的挑战是确保在Content-Type标头设置为“ application / json”的情况下进行请求。使用Postman,我的原始请求返回为“输入无效”。添加Content-Type标头可以解决我的问题。
答案 2 :(得分:4)
只需将[FromBody]
更改为[FromForm]
。
FromForm
属性用于由内容类型application/x-www-url-formencoded
发送的已提交表单中的传入数据,而FromBody
将解析模型的默认方式,在大多数情况下,该方式由内容类型发送application/json
,来自请求正文。
感谢https://stackoverflow.com/a/50454145/5541434
答案 3 :(得分:0)
就像mjwills和DavidG所说的那样,您可能应该在控制器参数实现中使用一个具体的类,例如:
public class MyClass
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}
答案 4 :(得分:0)
如果您在浏览器上检查“网络”选项卡,您会注意到表单正在将输入值作为参数发送到url,而不是发送本身。因此,将其命名为 value 不会将名为“ value”的属性发送到您的服务器。
相反,post方法期望一个名为 value 的属性,该属性可以是任何类型(因为它是一个Object),并且该参数永远不会实现,因为它正在接收其他参数:PropertyA,PropertyB和文件。
您的完整帖子网址现在应该看起来像这样:
https://localhost:44352/api/tool?PropertyA=X&PropertyB=Y&Files=Z
还请注意,您没有为您的 Post 方法指定网址,因此我不确定客户端如何到达 / api / Tool 。您可能需要在控制器上指定该url,并添加 Route 属性:
[Route(“ api / tool”)]
如果您的控制器名为Api,则自然路由为Hostname / Controller / Method或https://localhost:44352/api/post。否则,它将用控制器名称替换“ api”。
答案 5 :(得分:0)
将正文文本类型更改为所需的格式,例如从文本更改为JSON(应用程序)。
答案 6 :(得分:0)
我遇到了同样的问题,我的解决方案是禁用depi属性ApiController,我不知道您为什么可以阅读此内容[https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-2.2#multipartform-data-request-inference],我不明白这是什么问题
[Produces("application/json")]
[Route("api/[controller]")]
//[ApiController]<<remove this
public class PagosController : ControllerBase
您采用方法
[HttpPost("UploadDescuento")]
public async Task<IActionResult> UploadDescuento(IEnumerable<IFormFile> files)
答案 7 :(得分:0)
JavaScript和DotNet Core Web API实现。希望这对外面的人有帮助。
//JavaScript
var dataList = [];
var dataObject = {};
dataObject["field1"] = "field1";
dataObject["field2"] = "field2";
dataList.push(dataObject);
$.ajax("https://localhost:1111/api/Sample",
{
type: "POST",
async: false,
contentType: "application/json",
dataType: 'json',
data: JSON.stringify(dataList),
success: function (responseObject) {
console.log(responseObject);
}
});
//DOT NET CORE WEB API
//Sample Request Model
public class RequestObject{
public string field1 { get; set; }
public string field2 { get; set; }
}
[Route("api/[controller]")]
[ApiController]
public class SampleController : ControllerBase
{
//Sample POST API
[HttpPost]
public string Post([FromBody] List<RequestObject> requestObjectList)
{
var youWelcome = requestObjectList;
return "JavaScript Post Successful.";
}
}