查询Durable Entity状态时Http函数崩溃如何返回JSON
问题背景
我是Azure Functions与Durable Entities的初学者,计划实现以下功能:
- 创建一个持久实体,其包含名为
systemList的状态 - 创建队列触发器函数消费队列内的消息,并将消息存储到前述创建的实体状态中
- 创建Http触发器函数获取实体的当前状态
我在实现第三步时遇到问题:本地运行发送Http查询请求时程序直接停止运行,但把返回行从直接返回stateResponse.EntityState改成拼接空字符串后程序可以正常返回字符串,但我需要返回标准JSON格式响应。
问题相关代码
HttpTriggerFunction.cs
using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Azure.WebJobs.Extensions.DurableTask; using System.Net.Http; using System.Net; using Newtonsoft.Json.Linq; namespace **.Function { public static class HttpTriggerQueryEntity { [FunctionName("QueryEntity")] public static async Task<HttpResponseMessage> Run( [HttpTrigger(AuthorizationLevel.Function)] HttpRequestMessage req, [DurableClient] IDurableEntityClient client) { var entityId = new EntityId(nameof(ProcessingListEntity), "processing_message_total"); EntityStateResponse<JObject> stateResponse = await client.ReadEntityStateAsync<JObject>(entityId); //await client.SignalEntityAsync(entityId, "Empty"); return req.CreateResponse(HttpStatusCode.OK,stateResponse.EntityState); } } }
blockData.cs
#nullable enable using System; namespace **.Function { public class BlockData { public string? id { get; set; } public string? SessionId { get; set; } public string? MachineId { get; set; } public DateTime? Start { get; set; } public DateTime? End { get; set; } public string? Activity {get; set;} public string? BlobId { get; set; } } }
Entity.cs
using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Newtonsoft.Json; using Microsoft.Azure.WebJobs.Extensions.DurableTask; using System.Collections.Generic; namespace **.Function { [JsonObject(MemberSerialization.OptIn)] public class ProcessingListEntity { public ProcessingListEntity(){ systemList = new Dictionary<string, BlockData>(); } [JsonProperty("systemList")] public Dictionary<string, BlockData> systemList {get; set;} public void Add(BlockData blockData) { if (!this.systemList.ContainsKey(blockData.MachineId)) { this.systemList.Add(blockData.MachineId, blockData); return; } else { this.systemList[blockData.MachineId].Start = blockData.Start; this.systemList[blockData.MachineId].End = blockData.End; } } public void Empty() => this.systemList = new Dictionary<string, BlockData>(); public Dictionary<string, BlockData> Get() => this.systemList; [FunctionName(nameof(ProcessingListEntity))] public static Task Run([EntityTrigger] IDurableEntityContext ctx) => ctx.DispatchAsync<ProcessingListEntity>(); } }
问题复现
直接运行时,使用如下返回代码会导致程序崩溃停止:
return req.CreateResponse(HttpStatusCode.OK,stateResponse.EntityState);
将代码修改为如下内容后程序可正常运行,但返回的是普通字符串,不符合JSON返回要求:
return req.CreateResponse(HttpStatusCode.OK,stateResponse.EntityState + "");
修复方案
问题核心是读取实体状态时使用了错误的泛型类型,且返回时未明确指定JSON序列化格式,按以下步骤修改即可:
- 不要用
JObject作为ReadEntityStateAsync的泛型参数,直接使用定义的实体强类型ProcessingListEntity读取状态,避免跨序列化器类型不匹配导致的崩溃 - 返回响应时明确指定
application/json媒体类型,确保返回标准JSON格式 - 增加实体存在性判断,避免实体未初始化时触发空引用异常
修改后的HttpTriggerFunction.cs代码如下:
using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.Azure.WebJobs.Extensions.DurableTask; using System.Net.Http; using System.Net; using System.Net.Http.Formatting; namespace **.Function { public static class HttpTriggerQueryEntity { [FunctionName("QueryEntity")] public static async Task<HttpResponseMessage> Run( [HttpTrigger(AuthorizationLevel.Function)] HttpRequestMessage req, [DurableClient] IDurableEntityClient client) { var entityId = new EntityId(nameof(ProcessingListEntity), "processing_message_total"); // 使用强类型读取实体状态 EntityStateResponse<ProcessingListEntity> stateResponse = await client.ReadEntityStateAsync<ProcessingListEntity>(entityId); // 实体不存在时返回404 if (!stateResponse.EntityExists) { return req.CreateResponse(HttpStatusCode.NotFound, new { error = "Entity not found" }, JsonMediaTypeFormatter.DefaultMediaType); } // 明确指定返回JSON格式 return req.CreateResponse(HttpStatusCode.OK, stateResponse.EntityState, JsonMediaTypeFormatter.DefaultMediaType); } } }
补充说明:之前拼接空字符串能正常运行,是因为JObject拼接字符串时会隐式调用ToString()输出JSON字符串,但Azure Functions默认序列化器处理JObject类型时会出现序列化配置不匹配、循环引用等问题,直接导致宿主进程崩溃,使用强类型读取+明确指定JSON媒体类型可以完全规避这个问题。
内容的提问来源于stack exchange,提问作者superDu
相关产品推荐
相关产品推荐

