繁体   English   中英

ASP.NET MVC操作针对无效JSON返回500

[英]ASP.NET MVC Action returns 500 on invalid JSON

我正在创建一个供合作伙伴公司上传报告的API,它看起来像这样:

[Route("UploadReport"), HttpPost]
public async Task<ActionResult> UploadReport(CancellationToken cancellationToken)
{
    if (Request.ContentType?.ToLower()?.StartsWith("application/json") != true)
    {
        return new MyJsonResult(HttpStatusCode.UnsupportedMediaType, "{\"Error\":\"Content-Type must be \\\"application\\/json\\\"\"}");
    }

    var json = new { reportContentType = "", reportContent = "" };
    Request.InputStream.Seek(0, SeekOrigin.Begin);

    try
    {
        json = JsonConvert.DeserializeAnonymousType(await new StreamReader(Request.InputStream, GetRequestEncoding(Request)).ReadToEndAsync(), json);
    }
    catch
    {
        return new MyJsonResult(HttpStatusCode.BadRequest, "{\"Error\":\"Failed to parse the JSON.\"}");
    }

    // From here, I go on to store the result and return an OK response.
}

关键是我想要求他们发送Content-Type: application/json标头,并且如果我无法解析JSON,我想返回400 Bad Request

但是,如果我发送带有无效JSON的POST (请注意"text/html"之后的逗号):

POST https://[debug-server]/UploadReport HTTP/1.1
Host: [debug-server]
Content-Length: 95
Content-Type: application/json

{
  "reportContentType":"text/html"
  "reportContent":"<h2>This is an example report</h2>"
}

我收到此500错误:

500错误

(因此您可以搜索此内容):

Server Error in '/' Application.

...

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ArgumentException: Invalid object passed in, ':' or '}' expected. (41): {
  "reportContentType":"text/html"
  "reportContent":"<h2>This is an example report</h2>"
}

Source Error: 


An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.  

Stack Trace: 



[ArgumentException: Invalid object passed in, ':' or '}' expected. (41): {
  "reportContentType":"text/html"
  "reportContent":"<h2>This is an example report</h2>"
}]
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth) +1251
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth) +123
System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer) +79
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit) +37
System.Web.Mvc.JsonValueProviderFactory.GetDeserializedObject(ControllerContext controllerContext) +213
System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext) +16
System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) +69
System.Web.Mvc.ControllerBase.get_ValueProvider() +30
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +62
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +105
System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__19(AsyncCallback asyncCallback, Object asyncState) +743
System.Web.Mvc.Async.WrappedAsyncResult`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +14
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +343
System.Web.Mvc.Controller.<BeginExecuteCore>b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +25
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +465
System.Web.Mvc.Controller.<BeginExecute>b__14(AsyncCallback asyncCallback, Object callbackState, Controller controller) +18
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +20
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +374
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +16
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +52
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +384
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155



--------------------------------------------------------------------------------
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.6.1087.0

如果我不包含Content-Type: application/json标头并删除该子句以要求它,那么它将正常工作。 因此,有些东西会看到具有Content-Type: application/json的请求Content-Type: application/json并尝试解析该请求,这会在无效JSON上引发异常。

所以我有两个问题:

是什么原因造成的?

我该如何预防?

查找请求验证。 把它关掉。 它必须有所帮助。

因此,这里的关键是删除签名中的所有参数。 因此,我可以使用Request.TimedOutToken代替采用CancellationToken类型的参数。 所以现在我的签名看起来像这样:

[Route("UploadReport"), HttpPost]
public async Task<ActionResult> UploadReport()

在方法中没有任何参数的情况下,MVC的请求处理程序退出,尝试解析JSON以为参数提供值,我可以自己从Request中解析JSON。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM