【问题标题】:Attribute routing is failing for MVC/WebApi combo projectMVC/WebApi 组合项目的属性路由失败
【发布时间】:2016-07-05 13:08:03
【问题描述】:

我正在尝试创建一个既是 MVC 又是 Web Api 的 ASP.NET 应用程序。默认控制器 (HomeController) 返回一个由一些 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 时,它可以工作......只要我在查询字符串中发送参数。如果我在正文中发送参数,则会收到原始错误。

【问题讨论】:

  • 您正在使用的[Route][HttpPost] 属性的完整命名空间是什么?
  • 命名空间是namespace EncryptionDemo.Controllers。 ValuesController 是 ASP.NET 项目生成的默认控制器。我刚刚删除了 Index 方法并添加了我自己的方法。
  • 我询问了[Route][HttpPost] 属性的完整命名空间。不是控制器...
  • 对不起我的错误。 [HttpPost] = HttpPostAttribute.HttpPostAttribute() 和 [Route("encrypt")] = RouteAttribute.RouteAttribute(string template)
  • 这还不是完整的命名空间。确保您使用的是位于System.Web.Http 而不是System.Web.Mvc 中的那些。可悲的是,他们的名字完全相同

标签: asp.net-mvc asp.net-web-api2 attributerouting


【解决方案1】:

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

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

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

然后我修改了我的 API 方法以接受此类的类型

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

      // Do encryption stuff here

      return Ok(cipherText);
    }

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

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

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

这个post from Rick Strahl 帮我弄清楚了。 This page from Microsoft 参数绑定也解释说 最多允许从消息体中读取一个参数。

【讨论】:

    【解决方案2】:

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

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

    抱歉,这确实是编译时错误。我编辑我的代码。请复制并粘贴到您的代码中。如果我有帮助,标记为答案。

    【讨论】:

    • 我试过了,但是编译错误The name 'HttpPost' does not exist in the current context
    • 感谢您的帮助,但即使进行了更改,我仍然会遇到同样的错误
    猜你喜欢
    • 2019-10-17
    • 2015-01-24
    • 2016-12-17
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多