5

我是一名 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?

4

2 回答 2

6

如果您检查您发送的 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 binderpublic string DoAction([FromBody]RootObject myFoo)

于 2012-11-20T13:10:35.527 回答
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 动词,路由引擎将自动分派到相应的动作。

于 2012-11-20T12:56:45.003 回答