MVC/WebApi 组合项目的属性路由失败

Attribute routing is failing for MVC/WebApi combo project

我正在尝试创建一个 ASP.NET 既是 MVC 又是 Web Api 的应用程序。默认控制器(HomeController)returns 由一些HTML 和jQuery 组成的视图。我想使用 jQuery 来调用属于同一项目的 API。

我有 API 设置并一直在使用 Postman 对其进行测试,但在尝试到达 API 中的端点时出现以下错误。

{
  "Message": "No HTTP resource was found that matches the request URI 'http://localhost:19925/api/encryption/encrypt'.",
  "MessageDetail": "No action was found on the controller 'Values' that matches the request."
}

我正在尝试使用属性路由,所以我很确定这就是我出错的地方。

    [RoutePrefix("api/encryption")]
    public class ValuesController : ApiController
    {
        [HttpPost]
        [Route("encrypt")]
        public IHttpActionResult EncryptText(string plainText, string keyPassPhrase)
        {
            // Method details here

            return Ok(cipherText);
        }
}

我将路由前缀设置为 api/encryption。我也有使用路由 encrypt 并标记为 HttpPost 的方法。下面是我的 WebApiConfig,我认为它已针对属性路由进行了正确配置。

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

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

据我理解POST到下面URL应该达到的方法..

http://localhost:19925/api/encryption/encrypt

但事实并非如此。我通过 Postman 将这两个字符串值发布到该方法。我附上了一个屏幕截图(是的,keyPassPhrase 是假的)。

这是要求的 global.asax ...

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

还有一件事要注意……当我在 Postman 中从 GET 更改为 POST 时,它可以正常工作……只要我在查询字符串中发送参数即可。如果我在正文中发送参数,我会收到原始错误。

试试下面的代码。它会起作用:

[RoutePrefix("api/encryption")]
    public class ValuesController : ApiController
    {

        [Route("encrypt"),HttpPost]
        public IHttpActionResult EncryptText(string plainText, string keyPassPhrase)
        {
            // Method details here

            return Ok(cipherText);
        }
}

对不起,亲爱的,这真的是编译时错误。我编辑我的代码。请将其复制并粘贴到您的代码中。如果我有帮助,请标记为答案。

问题是我试图将两个值 POST 传递给接受两个参数的 API 方法。这对于 API 是不可能的(当然也不是没有一些变通方法),因为 API 方法需要一个对象而不是两种不同的原始类型(即字符串)。

这意味着在服务器端我需要创建一个简单的 class 来保存我想要传递的值。例如...

public class EncryptionPayload
{
    public string PlainText { get; set; }
    public string PassPhrase { get; set; }
}

然后我修改了我的 API 方法以接受这种类型 class

    [Route("encrypt")]
    [HttpPost]
    public IHttpActionResult EncryptText(EncryptionPayload payload)
    {
      string plainText = payload.PlainText;
      string passPhrase = payload.PassPhrase

      // Do encryption stuff here

      return Ok(cipherText);
    }

然后在该控制器内,我从 EncryptionPayload class 实例中提取了我需要的 Strings。在客户端,我需要像这样将数据作为 JSON 字符串发送 ..

{"plainText":"this is some plain text","passPhrase":"abcdefghijklmnopqrstuvwxyz"}

更改这些内容后,Postman 一切正常。最后我没有考虑 Model Binding,而是认为接受 POST 的 API 端点可以接受多个原始值。

关于参数绑定的post from Rick Strahl helped me figure it out. This page from Microsoft也解释说最多允许从消息正文中读取一个参数。