【问题标题】:A simple post request wont route to a web api control一个简单的 post 请求不会路由到 web api 控件
【发布时间】:2018-02-06 13:43:50
【问题描述】:

这是WebApiConfig.cs中路由的配置

// Web API configuration and services
config.Routes.MapHttpRoute(
  name: "ActionApi",
  routeTemplate: "api/{controller}/{action}");
// Web API routes



config.Routes.MapHttpRoute(
  name: "DefaultApi",
  routeTemplate: "api/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional }
);

config.Routes.MapHttpRoute(
  name: "DefaultAdpi",
  routeTemplate: "api/ms/{controller}/{action}",
  defaults: new { id = RouteParameter.Optional }
);

config.Routes.MapHttpRoute(
  name: "MSApi",
  routeTemplate: "api/{controller}/ms/{action}",
  defaults: new { controller="GPI" }
);
config.MapHttpAttributeRoutes();

这是我的控制器。

  [HttpPost]
    public IHttpActionResult payout(string t)
    {

这是httpRequest

POST /api/Race/payout HTTP/1.1
Host: localhost
User-Agent: PostmanRuntime/7.1.1
Content-Length: 4
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Postman-Token: f2adaf2e-d518-4924-bd28-8a901bd1846f
X-Forwarded-For: 84.228.5.88
X-Forwarded-Proto: https
X-Original-Host: integerator.eu.ngrok.io

t=da

我在这个控制器中有一些功能。控制器的名称没有问题。动作被调用。

更多细节。如果我使用 [FromBody] 属性,我会得到 t 值为 null。

[HttpPost]
    public IHttpActionResult payout([FromBody]string t)
    {

t 变量为空。

我必须将 t 作为字符串变量。我不想把它改成另一种类型。

请帮助我理解这种尴尬的路由行为。

更新

我有以下两个动作:

 [HttpPost]
    public IHttpActionResult payout(string t)
    {

   public IHttpActionResult payout([FromBody] Object req)
        {

我提到的 http 请求总是转到第二个支付操作,而不是第一个操作。 我希望使用字符串参数的第一个操作拦截该发布请求。 我不明白为什么第一个动作没有处理请求。即使完全删除第二个操作也是如此。

我尝试使用名为“Post man”的工具发布不同的 http 内容类型标头。

这是我仅在控制器中执行第一个操作时遇到的错误,

{
"Message": "No HTTP resource was found that matches the request URI 'http://localhost:55392/api/Race/payout'.",
"MessageDetail": "No action was found on the controller 'Race' that 

matches the request."
}

我考虑过用对象覆盖模型绑定,这里描述的方式:

https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

但我不认为有什么相关的。有没有办法破解路由的工作方式并拦截传入的请求?

【问题讨论】:

    标签: asp.net-web-api


    【解决方案1】:

    首先,在这种情况下你必须使用FromBody属性,因为string是一个简单的类型,默认是从Url反序列化的。详情请查看文章Parameter Binding in ASP.NET Web API。否则,只要您没有可以匹配缺少的 t 参数的路由,您将收到 404 错误。

    但是,正如您在问题中指出的那样,如果使用 FromBody,您将在 t 变量中获得空值。当您发送 form-urlencoded 数据时,ASP.NET Web Api 使用FormUrlEncodedMediaTypeFormatter 反序列化请求数据。这个格式化程序通过将请求中的键值映射到持有对象的属性或字段来完成他的工作。因此,如果您声明以下类:

    public class SomeClass
    {
        public string T { get; set; }
    }
    

    并将您的操作更改为

    [HttpPost]
    public IHttpActionResult payout([FromBody] SomeClass obj)
    {
        // ...
    }
    

    并发送相同的请求,您将获得带有T 属性的obj 实例,其中填充了"da" 值。

    使用默认的 form-urlencoded 媒体类型格式化程序,您不能发送相同的请求并将数据直接反序列化为字符串变量。

    以下是使用从正文反序列化的字符串变量来保持操作的选项:

    1. 将请求内容类型更改为application/json,并在请求正文中发送以下数据(值周围的引号是必需的):

      “达”

      JsonMediaTypeFormatter 将正确反序列化此类字符串值。

    2. 如果您想保留内容类型,那么您应该为将直接反序列化为字符串的 form-urlencoded 数据实现自定义媒体类型格式化程序。有很多示例如何实现自定义格式化程序。以下是其中一些:

      Simple Custom Media Formatter in ASP.Net Web API

      Creating Custom CSVMediaTypeFormatter In ASP.NET Web API for Comma-Separated Values (CSV) Format

    希望这会有所帮助。

    【讨论】:

    • 我想问一个更好的解决方案。但在此之前,我确实有接受 post 请求并具有简单类型(例如 string、int、decimal 等)的 post 控制器。它们的参数绑定到请求参数。我希望控制器能够识别不同的对象。当请求到达带有任何对象参数的每个控制器时,每个控制器都是针对路由系统的。所以它会抛出“存在多个操作来处​​理”请求的错误。另一件事,我不想反序列化 json。这是一个简单的 http post 请求。我也不认为我需要一个可以在全球范围内工作的格式化程序
    • 我也从 Postman 发帖。没有内容类型使请求工作。我也无法影响请求参数,因为我使用的是外部 api 提供者。
    • 您的 cmets 与您的原始问题无关。考虑针对您描述的案例提出一个新问题。
    • 嗯,您在第一个问题中添加了一个全新的问题。这是一种不好的做法。
    • 我认为这个问题很容易理解。它只是简单地将 post 请求路由到带有字符串参数的 post 控制器。那么你能给我一个答案的方向吗?
    猜你喜欢
    • 2019-11-25
    • 2015-09-10
    • 1970-01-01
    • 2018-07-09
    • 2021-04-02
    • 1970-01-01
    • 2012-04-03
    • 2020-11-24
    • 1970-01-01
    相关资源
    最近更新 更多