【问题标题】:ASP.Net Web API 2 attribute-routed HTTP POST action not getting correct parameterASP.Net Web API 2 属性路由的 HTTP POST 操作未获得正确的参数
【发布时间】:2015-03-20 02:40:51
【问题描述】:

我有一个简单的 ASP.Net Web API 2 控制器:

public class TestController : ApiController
{
    [Route("api/method/{msg?}")]
    [AcceptVerbs("GET", "POST")]
    public string Method(string msg = "John")
    {
        return "hello " + msg;
    }
}

还有一个简单的 HTML 表单来测试它。

<form action="/api/method/" method="post">
    <input type="text" name="msg" value="Tim" />
    <input type="submit" />
</form>

当我加载页面并提交表单时,结果字符串为"hello John"。如果我将表单的方法从post 更改为get,结果将更改为"hello Tim"。为什么msg 参数在发布到控制器时没有被路由到操作?

========== 编辑 1 ==========

以防万一 HTTP GET 分散注意力,此版本的控制器也无法从发布的表单中接收正确的 msg 参数:

[Route("api/method/{msg?}")]
[HttpPost]
public string Method(string msg = "John")
{
    return "hello " + msg;
}

========== 编辑2 ==========

我没有更改默认路由,所以它仍然看起来像这样:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

【问题讨论】:

  • 出于兴趣,您为什么对 GET 和 POST 请求使用相同的方法?通常 GET 将用于检索资源,而 UPDATE / POST 将用于修改它。在这种情况下,接受两个动词的方法几乎没有意义 - 如果我不得不对冲赌注,如果你将这两种方法分开,你的问题将不是问题。
  • 真正的应用程序可能只使用 POST,但 GET 更容易在浏览器中粘贴为 URL。因此,除非有充分的理由来区分,否则我不会打扰。
  • 取决于您是否认为违反 REST 原则是一个很好的理由……我愿意!
  • 确实如此,尽管我要问的不是这个。我已经编辑了问题,为您添加了一个仅限 POST 的控制器。
  • 您是否更改了默认路由配置?如果是这样,请同时发布。

标签: asp.net-web-api asp.net-web-api2 asp.net-web-api-routing


【解决方案1】:

如果您使用的是 html formPOST 方法中的参数将不会被反序列化开箱即用。 Use the [FromBody] attribute 获取msg 的值。

[HttpPost]
[Route("api/method")]
public string Method([FromBody] string msg)
{
    return "hello " + msg;
}

否则,您必须使用Fiddler(或类似的网络调试器)调用POST 方法并将msg 作为查询字符串传递。

如果您真的喜欢使用 HTML Form 而不使用 [FromBody] 属性,请尝试以下操作

[HttpPost]
[Route("api/method")]
public string Method()
{
    var msg = Request.Content.ReadAsFormDataAsync();
    var res= msg.Result["msg"];
    return "hello " + res ;
}

【讨论】:

  • 谢谢。有趣的是[FromBody] 似乎不适用于可选参数。例如。如果我将代码更改为public string Method([FromBody] string msg = "John"),则调用将失败并显示InvalidOperationException,并显示消息“'FormatterParameterBinding' 不支持可选参数'msg'”
  • 我发现[FromBody] 带有一个可选的简单类型参数的解决方法是不使其成为可选,并根据您是否具有可选参数的值来以不同的方式构造您的请求正文:@ 987654337@ 然后 msg 在 WebAPI 中将是 "stringvalue"msg= 然后 msg 在 WebAPI 中将是 null。您必须在控制器方法中定义默认值"John",但这会消除InvalidOperationException。不要忘记将 Content-Type 标头设置为 application/x-www-form-urlencoded
猜你喜欢
  • 1970-01-01
  • 2017-12-23
  • 2015-10-09
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 2017-08-16
  • 2017-03-24
相关资源
最近更新 更多