找不到 blob 文件时出现 FunctionInvocationException
FunctionInvocationException when blob file not found
我正在创建一个函数来读取我们存储中的自定义文件。 function.json 与此类似:
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"route": "resource/{code}",
"methods": [
"get"
]
},
{
"type": "blob",
"name": "item",
"path": "data/20171003/{code}.json",
"connection": "blog_STORAGE",
"direction": "in"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
在 postman 中,如果我键入现有文件,它将正确调用该函数。另一方面,如果文件不存在,Azure 运行时将抛出错误:
{
"id": "4ef77dcd-f8ed-4327-9447-969da6b328a9",
"requestId": "0a9874dd-6a7b-4717-ae9f-c3c1e3bb16c8",
"statusCode": 500,
"errorCode": 0,
"message": "Exception while executing function: Functions.func_ativos -> Valor não pode ser nulo.\r\nNome do
parâmetro: stream",
"errorDetails": "Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception
while executing function: Functions.func_ativos --->
System.ArgumentNullException : Valor não pode ser nulo.\r\nNome do
parâmetro: stream\r\n at System.IO.StreamReader..ctor(Stream
stream,Encoding encoding,Boolean
detectEncodingFromByteOrderMarks,Int32 bufferSize,Boolean
leaveOpen)\r\n at System.IO.StreamReader..ctor(Stream stream)\r\n
at
Microsoft.Azure.WebJobs.Script.Binding.FunctionBinding.ConvertStreamToValue(Stream
stream,DataType dataType,Object& converted)\r\n at async
Microsoft.Azure.WebJobs.Script.Binding.FunctionBinding.BindStreamAsync(BindingContext
context,FileAccess access)\r\n at async
Microsoft.Azure.WebJobs.Script.Binding.ExtensionBinding.BindAsync(BindingContext
context)\r\n at async
Microsoft.Azure.WebJobs.Script.Description.NodeFunctionInvoker.ProcessInputBindingsAsync(Binder
binder,Dictionary2 executionContext,Dictionary
2 bindingData)\r\n
at async
Microsoft.Azure.WebJobs.Script.Description.NodeFunctionInvoker.InvokeCore(Object[]
parameters,FunctionInvocationContext context)\r\n at async
Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase.Invoke(Object[]
parameters)\r\n at async
Microsoft.Azure.WebJobs.Host.Executors.VoidTaskMethodInvoker2.InvokeAsync[TReflected,TReturnType](TReflected
instance,Object[] arguments)\r\n at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker
2.InvokeAsync[TReflected,TReturnValue](Object[]
arguments)\r\n at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker
invoker,ParameterHelper parameterHelper,CancellationTokenSource
timeoutTokenSource,CancellationTokenSource
functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan
timerInterval,IFunctionInstance instance)\r\n at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstance
instance,ParameterHelper parameterHelper,TraceWriter
traceWriter,ILogger logger,CancellationTokenSource
functionCancellationTokenSource)\r\n at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)\r\n
at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)
\r\n End of inner exception\r\n at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n
at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)\r\n
at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsync(IFunctionInstance
functionInstance,CancellationToken cancellationToken)\r\n at
Microsoft.Azure.WebJobs.Host.Executors.ExceptionDispatchInfoDelayedException.Throw()\r\n
at async Microsoft.Azure.WebJobs.JobHost.CallAsync(??)\r\n at async
Microsoft.Azure.WebJobs.Script.ScriptHost.CallAsync(String
method,Dictionary2 arguments,CancellationToken cancellationToken)\r\n
at async
Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.HandleRequestAsync(FunctionDescriptor
function,HttpRequestMessage request,CancellationToken
cancellationToken)\r\n at async
Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.ProcessRequestAsync(HttpRequestMessage
request,FunctionDescriptor function,CancellationToken
cancellationToken)\r\n at async
Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.<>c__DisplayClass3_0.<ExecuteAsync>b__0(??)\r\n
at async
Microsoft.Azure.WebJobs.Extensions.Http.HttpRequestManager.ProcessRequestAsync(HttpRequestMessage
request,Func
3 processRequestHandler,CancellationToken
cancellationToken)\r\n at async
Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.ExecuteAsync(HttpControllerContext
controllerContext,CancellationToken cancellationToken)\r\n at async
System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage
request,CancellationToken cancellationToken)\r\n at async
System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage
request,CancellationToken cancellationToken)\r\n at async
Microsoft.Azure.WebJobs.Script.WebHost.Handlers.SystemTraceHandler.SendAsync(HttpRequestMessage
request,CancellationToken cancellationToken)\r\n at async
Microsoft.Azure.WebJobs.Script.WebHost.Handlers.WebScriptHostHandler.SendAsync(HttpRequestMessage
request,CancellationToken cancellationToken)\r\n at async
System.Web.Http.HttpServer.SendAsync(HttpRequestMessage
request,CancellationToken cancellationToken)" }
我想在找不到文件时发送 404 状态代码,而不是像那样丑陋的堆栈(和错误 500)。我应该遵循的最佳方法是什么?
==更新
请注意,FunctionInvocationException 发生在 我的函数被调用之前。 Azure Functions Runtime 中似乎有一个错误,我不知道是错误还是预期。
我们也可以在 Azure 函数应用程序中捕获异常。在您的情况下,您可以捕获异常和 return http 状态代码 HttpStatusCode.NotFound
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
try
{
//Todo :Add your own logic
}
catch (Exception ex)
{
return req.CreateResponse(HttpStatusCode.NotFound);
}
return req.CreateResponse(HttpStatusCode.OK);
}
编辑:
正如您提到的,它发生在调用函数之前,似乎 return 由 Azure 函数集成 SDK 编辑。这也许是设计使然。我们也可以将我们的想法提供给 azure function team.
如果我们想要控制逻辑,我的解决方法是我们可以删除输入 blob 并自己实现自定义逻辑。我们可以从 Microsoft Azure Storage SDK for Node.js.
中获取示例代码
我正在创建一个函数来读取我们存储中的自定义文件。 function.json 与此类似:
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"route": "resource/{code}",
"methods": [
"get"
]
},
{
"type": "blob",
"name": "item",
"path": "data/20171003/{code}.json",
"connection": "blog_STORAGE",
"direction": "in"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
在 postman 中,如果我键入现有文件,它将正确调用该函数。另一方面,如果文件不存在,Azure 运行时将抛出错误:
{ "id": "4ef77dcd-f8ed-4327-9447-969da6b328a9", "requestId": "0a9874dd-6a7b-4717-ae9f-c3c1e3bb16c8", "statusCode": 500, "errorCode": 0, "message": "Exception while executing function: Functions.func_ativos -> Valor não pode ser nulo.\r\nNome do parâmetro: stream", "errorDetails": "Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: Functions.func_ativos ---> System.ArgumentNullException : Valor não pode ser nulo.\r\nNome do parâmetro: stream\r\n at System.IO.StreamReader..ctor(Stream stream,Encoding encoding,Boolean detectEncodingFromByteOrderMarks,Int32 bufferSize,Boolean leaveOpen)\r\n at System.IO.StreamReader..ctor(Stream stream)\r\n
at Microsoft.Azure.WebJobs.Script.Binding.FunctionBinding.ConvertStreamToValue(Stream stream,DataType dataType,Object& converted)\r\n at async Microsoft.Azure.WebJobs.Script.Binding.FunctionBinding.BindStreamAsync(BindingContext context,FileAccess access)\r\n at async Microsoft.Azure.WebJobs.Script.Binding.ExtensionBinding.BindAsync(BindingContext context)\r\n at async Microsoft.Azure.WebJobs.Script.Description.NodeFunctionInvoker.ProcessInputBindingsAsync(Binder binder,Dictionary2 executionContext,Dictionary
2 bindingData)\r\n
at async Microsoft.Azure.WebJobs.Script.Description.NodeFunctionInvoker.InvokeCore(Object[] parameters,FunctionInvocationContext context)\r\n at async Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase.Invoke(Object[] parameters)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.VoidTaskMethodInvoker2.InvokeAsync[TReflected,TReturnType](TReflected instance,Object[] arguments)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker
2.InvokeAsync[TReflected,TReturnValue](Object[] arguments)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker,ParameterHelper parameterHelper,CancellationTokenSource timeoutTokenSource,CancellationTokenSource functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan timerInterval,IFunctionInstance instance)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstance instance,ParameterHelper parameterHelper,TraceWriter traceWriter,ILogger logger,CancellationTokenSource functionCancellationTokenSource)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??) \r\n End of inner exception\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsync(IFunctionInstance functionInstance,CancellationToken cancellationToken)\r\n at Microsoft.Azure.WebJobs.Host.Executors.ExceptionDispatchInfoDelayedException.Throw()\r\n at async Microsoft.Azure.WebJobs.JobHost.CallAsync(??)\r\n at async Microsoft.Azure.WebJobs.Script.ScriptHost.CallAsync(String method,Dictionary2 arguments,CancellationToken cancellationToken)\r\n at async Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.HandleRequestAsync(FunctionDescriptor function,HttpRequestMessage request,CancellationToken cancellationToken)\r\n at async Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.ProcessRequestAsync(HttpRequestMessage request,FunctionDescriptor function,CancellationToken cancellationToken)\r\n at async Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.<>c__DisplayClass3_0.<ExecuteAsync>b__0(??)\r\n at async Microsoft.Azure.WebJobs.Extensions.Http.HttpRequestManager.ProcessRequestAsync(HttpRequestMessage request,Func
3 processRequestHandler,CancellationToken cancellationToken)\r\n at async Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.ExecuteAsync(HttpControllerContext controllerContext,CancellationToken cancellationToken)\r\n at async System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n at async System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n at async Microsoft.Azure.WebJobs.Script.WebHost.Handlers.SystemTraceHandler.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n at async Microsoft.Azure.WebJobs.Script.WebHost.Handlers.WebScriptHostHandler.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)\r\n at async System.Web.Http.HttpServer.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)" }
我想在找不到文件时发送 404 状态代码,而不是像那样丑陋的堆栈(和错误 500)。我应该遵循的最佳方法是什么?
==更新
请注意,FunctionInvocationException 发生在 我的函数被调用之前。 Azure Functions Runtime 中似乎有一个错误,我不知道是错误还是预期。
我们也可以在 Azure 函数应用程序中捕获异常。在您的情况下,您可以捕获异常和 return http 状态代码 HttpStatusCode.NotFound
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
try
{
//Todo :Add your own logic
}
catch (Exception ex)
{
return req.CreateResponse(HttpStatusCode.NotFound);
}
return req.CreateResponse(HttpStatusCode.OK);
}
编辑:
正如您提到的,它发生在调用函数之前,似乎 return 由 Azure 函数集成 SDK 编辑。这也许是设计使然。我们也可以将我们的想法提供给 azure function team.
如果我们想要控制逻辑,我的解决方法是我们可以删除输入 blob 并自己实现自定义逻辑。我们可以从 Microsoft Azure Storage SDK for Node.js.
中获取示例代码