简单的ApiController方法:
public class TestController : ApiController
{
public void TakeIt(MyObject o){
Console.Write(o.ToString());
}
}
简单数据类型:
public class MyObject{
public string V1{ get; set; }
public string V2{ get; set; }
}
简单的帖子:
POST http://localhost:11026/api/test/takeit HTTP/1.1
Accept: application/json
Content-Type: application/json
Host: localhost:11026
{"V1":"Something","V2": "Something else"}
由于某种原因,MyObject o不会自动从JSON表单post body绑定(即使在方法的参数之前插入了[FromBody]
。
我做错了吗?
解决方案(DUH!)
为了调试我的传入请求,我把它放在我的global.asax中(因为我没有得到流经Fiddler的请求)所以我可以先检查它们
protected void Application_BeginRequest()
{
using (Stream receiveStream = Request.InputStream)
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
var content = readStream.ReadToEnd();
Console.WriteLine(content);
}
}
}
这阻止了阅读发布数据的任何内容。当我删除它时,自动模型绑定工作正常。
答案 0 :(得分:1)
我认为您需要使用[HttpPost]修饰您的方法或将其重命名为PostTakeIt。 Web API默认为GET我相信。
答案 1 :(得分:1)
两件事
public class TestController : ApiController
{
[HttpPost]
public void TakeIt([FromBody]MyObject o){
Console.Write(o.ToString());
}
}
使用HttpPost
标记操作,因为它实际上不符合基于约定的路由,然后使用[FromBody]
标记参数,以便模型绑定器知道在哪里查找模型。
另外,给定URI api/test/takeit
,这里的假设是路由模板为api/{controller}/{action}
。
默认模板通常为api/{controller}/
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
不符合动作名称。
你要么必须添加另一条路线
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
或使用属性路由
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
使用更新的控制器
[RoutePrefix("api/test")]
public class TestController : ApiController
{
[HttpPost]
[Route("takeit")] //Matches POST api/test/takeit
public IHttpActionResult TakeIt([FromBody]MyObject o){
Console.Write(o.ToString());
return Ok();
}
}