MVC Web API POST实体(500内部服务器错误)

时间:2013-10-12 14:42:52

标签: c# asp.net-mvc asp.net-web-api

我一直致力于为我公司的网站构建API。我已经为我的所有GET工作做得很好,并且像我想要的那样返回JSON。

我在使用POST创建新记录方面遇到了问题。我正在向我的控制器发送JSON。如果我的控制器接受字符串或对象参数,但在期望模型时不起作用,则此方法正常。

在我的api控制器中,我有这个方法:

[HttpPost]
public void POSTEstimate(Estimate estimate)
{
    //never makes it to the first line when expecting a Model (Estimate)
}

从我一直阅读的内容来看,Web API应该能够反序列化自动发布的JSON(并将其放入我的模型中),但我总是得到500内部服务器错误。当我告诉它接受一个字符串时,该方法工作正常。

有什么显而易见的我在这里做错了吗?

编辑:这是我用来调用API方法的测试页面的堆栈跟踪:

[WebException: The remote server returned an error: (500) Internal Server Error.]
   System.Net.HttpWebRequest.GetResponse() +6120419
   PDR.Controllers.AdminController.test() in c:\PDR\PDR\PDR\Controllers\AdminController.cs:714
   lambda_method(Closure , ControllerBase , Object[] ) +96
   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +205
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
   System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +28
   System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +50
   System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +58
   System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +237
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +12
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +50
   System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +24
   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +126
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +45
   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +14
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +25
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +61
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +25
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +49
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +25
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +49
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9042109
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

2 个答案:

答案 0 :(得分:1)

与其他REST框架一样,Web API鼓励并支持使用可序列化为JSON DTO的POCO。序列化似乎失败了。

如果没有客户端代码(应该为POST创建格式正确的JSON主体),正确设置发布为application / json的内容类型,很难分辨出客户端代码的哪一部分不正确。

报告为内部服务器错误的错误没有帮助。甚至没有查看StackTrace就无法访问您的代码这一事实清楚地表明问题出现在框架代码中。该框架期望格式正确的DTO,因此比较POST的DTO与DTO的定义OR构造并序列化DTO的实例并比较实际的字符串。

答案 1 :(得分:0)

今天我遇到了类似的问题,我的问题是我的控制器中有多个可能的操作,可以被Web Api使用,但是无法知道使用哪一个。所以在我的情况下,我使用最长的客户端和服务器端进行操作,而不是依赖于默认的api路由:

路由器:

config.Routes.MapHttpRoute(
            name: "ApiWithAction",
            routeTemplate: "metadataApi/{controller}/{action}/{id}",
            defaults: new {id = RouteParameter.Optional});

Ajax电话:

[...]
var options = {
    url: basePath + 'metadataapi/employee/FetchPage',
    type: 'POST',
    data: filter,
    dataType: 'json'
};

return $.ajax(options);