从WebApi获取"未找到任何操作"

use*_*169 5 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"}
Run Code Online (Sandbox Code Playgroud)

我的控制器看起来像这样:

public class PublicController : ApiController
{
    [HttpPost]
    public string DoAction(string myParam)
    {
        return "Test";
    }
} 
Run Code Online (Sandbox Code Playgroud)

并且,路由块看起来像这样:

    config.Routes.MapHttpRoute(
        name: "PublicApi",
        routeTemplate: "api/{controller}/{action}"
    );
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

{
    "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."
}
Run Code Online (Sandbox Code Playgroud)

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

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

Mar*_*nes 6

If you examine the JSON you were sending {"myParam":"test"} then you will see what Darin points out i.e. you need a Model to contain your property e.g. run {"myParam":"test"} into the following tool: http://json2csharp.com/ and you get:

public class RootObject
{
    public string myParam { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Your previous method signature with the simple type of string would have been treated by WebApi as a UrlParameter by default (the same as public string DoAction([FromUri]string myFoo)). You can prove this as leaving you code as is this url should work:

http://localhost:50381/Api/Public/DoAction?myParam=something
Run Code Online (Sandbox Code Playgroud)

The body serialiser using JSON.NET won't be able to parse a simple .NET type on it's own and therefore you need to create a simple Model to host it on. This will then use the from body binder public string DoAction([FromBody]RootObject myFoo)