【问题标题】:Getting "No action was found" from WebApi从 WebApi 获取“未找到任何操作”
【发布时间】:2013-06-01 00:45:28
【问题描述】:

我是一名 WCF 开发人员,是 MVC 的新手。尝试将我的 WCF API 作为 ApiControllers 集成到 MVC 应用程序中(是否值得努力仍然是个大问题)。

我有一个来自 jQuery 插件的请求:

 POST http://localhost:18698/Api/Public/DoAction HTTP/1.1 
 ....
 Content-Type: application/json; charset=UTF-8 Accept:
 application/json, text/javascript, */*; q=0.01

 {"myParam":"test"}

我的控制器如下所示:

public class PublicController : ApiController
{
    [HttpPost]
    public string DoAction(string myParam)
    {
        return "Test";
    }
} 

而且,路由部分如下所示:

    config.Routes.MapHttpRoute(
        name: "PublicApi",
        routeTemplate: "api/{controller}/{action}"
    );

我收到此错误:

{
    "Message": "No HTTP resource was found that matches the request URI 'http://localhost:18698/Api/Public/DoAction'.",
    "MessageDetail": "No action was found on the controller 'Public' that matches the request."
}

不接受任何 JSON 参数的方法工作正常,但接受 JSON 参数的方法不工作。我必须能够将复杂的 JSON 传递给方法。在 WCF 中,从 JSON 到对象的转换由 WCF 为我处理。

你知道我为什么会收到这个错误吗?我能否像在 WCF 中一样在 MVC 中无缝地传递/接收复杂的 JSON?

【问题讨论】:

  • application/x-www-form-urlencoded 格式发布是否有效? (只是想排除您的 JSON 无效的可能性)
  • 我将 myParam=test 发布为 Content-Type: application/x-www-form-urlencoded;字符集=UTF-8。结果相同——在控制器上没有找到任何操作
  • 您的路线似乎没问题,尝试将DoAction 更改为Post 并删除[HttpPost] 属性,动词类型隐含在ApiController 中的动作名称中。跨度>

标签: json asp.net-web-api


【解决方案1】:

如果您检查您发送的 JSON {"myParam":"test"},那么您将看到 Darin 指出的内容,即您需要一个模型来包含您的属性,例如将 {"myParam":"test"} 运行到以下工具中:http://json2csharp.com/ 你会得到:

public class RootObject
{
    public string myParam { get; set; }
}

默认情况下,WebApi 会将您之前使用简单类型字符串的方法签名视为 UrlParameter(与 public string DoAction([FromUri]string myFoo) 相同)。您可以证明这是留下您的代码,因为这个 url 应该可以工作:

http://localhost:50381/Api/Public/DoAction?myParam=something

使用 JSON.NET 的主体序列化程序无法自行解析简单的 .NET 类型,因此您需要创建一个简单的模型来托管它。然后这将使用 from body binder public string DoAction([FromBody]RootObject myFoo)

【讨论】:

    【解决方案2】:

    一如既往地从定义视图模型开始:

    public class MyModel
    {
        public string MyParam { get; set; }
    }
    

    然后让您的控制器操作将此视图模型作为参数:

    public class PublicController : ApiController
    {
        [HttpPost]
        public string DoAction(MyModel model)
        {
            return "Test_" + model.MyParam;
        }
    }
    

    最终调用控制器动作:

    <script type="text/javascript">
        $.ajax({
            url: '@Url.HttpRouteUrl("PublicApi", new { controller = "public", action = "doaction" })',
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({ "myParam": "test" }),
            sucecss: function (result) {
                console.log(result);
            }
        });
    </script>
    

    备注:您在路由中包含操作名称违反了 RESTful 约定。在 RESTful 路由中,您使用的是资源,而不是操作。因此,您的控制器代表您正在操作的资源,而 HTTP 动词代表您正在调用的操作。因此,您可以使用 Get、Post、Patch 和 Delete 等动作名称,并根据客户端使用的 HTTP 动词,路由引擎将自动分派到相应的动作。

    【讨论】:

    • 关于违反 REST 的公平点......但是,OP 从未提及任何关于 API 是 RESTful 的内容。
    • 那行得通。谢谢。这是否意味着 JSON 参数必须始终包装在 MVC 中? (在 WCF 中,有一个选项 Wrapped vs bare。)另外,您是否知道 JSON 序列化程序 MVC 正在使用什么。再次感谢。
    • @user1044169 JSON.NET 默认james.newtonking.com/projects/json-net.aspx
    • @user1044169,为了更好地了解模型绑定在 ASP.NET Web API 中的工作原理,我邀请您查看以下文章:blogs.msdn.com/b/jmstall/archive/2012/04/16/…。此外,标准 ASP.NET MVC 控制器使用 MS JavaScriptSerializer,ApiControllers 使用 JSON.NET 进行 JSON 序列化。
    猜你喜欢
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 2019-02-16
    • 2019-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    相关资源
    最近更新 更多