从Web Api获得“没有找到任何行动”

时间:2012-11-20 12:35:36

标签: json asp.net-web-api

我是一名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中,WCF为我处理了从JSON到对象的转换。

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

2 个答案:

答案 0 :(得分:6)

如果您检查了发送{"myParam":"test"}的JSON,那么您将看到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)

答案 1 :(得分: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动词,路由引擎将自动调度到相应的动作。