You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Azure Function返回资源组及列表异常问题排查

问题背景

正在开发基于Azure Functions的API,需要实现两类查询逻辑:

  • 传入订阅ID、不指定资源组名时,返回对应订阅下的所有资源组名称列表
  • 传入订阅ID+资源组名时,返回指定资源组的ID
    现有代码实现如下:
[Function("getRg")]
public async Task<HttpResponseData> GetRgs([HttpTrigger(AuthorizationLevel.Function, "get", Route = "rg")] HttpRequestData req,
        string? rg, string sub,
        FunctionContext functionContext)
{
    ArmClient client = new ArmClient(new DefaultAzureCredential());

    SubscriptionCollection subscriptions = client.GetSubscriptions();
    SubscriptionResource subscription = await subscriptions.GetAsync(sub);

    ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();

    if (!string.IsNullOrEmpty(rg))
    {
        string resJson = "";
        ResourceGroupResource resourceGroup = await resourceGroups.GetAsync(rg);
        resourceGroup = await resourceGroup.GetAsync();
        resJson = JsonSerializer.Serialize(resourceGroup.Data.Id);

        _logger.LogInformation($"requested RG: ${resJson}");

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString(resJson);

        return response;
    }
    else 
    {
        var rgList = new List<string>();

        foreach (var rgItem in resourceGroups)
        {
            rgList.Add(rgItem.Data.Name);
        }

        _logger.LogInformation($"rg list: {rgList}");

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/html, charset=utf-8");
        await response.WriteAsJsonAsync(rgList);

        return response;
    }
}
已复现的问题
  1. 不传入rg参数查询资源组列表时,函数抛出异常:

System.Private.CoreLib: Exception while executing function: Functions.getRg. System.Private.CoreLib: Result: Failure
Exception: System.AggregateException: One or more errors occurred. (The format of value 'text/plain, charset=utf-8' is invalid.)

  1. 查询单个资源组ID时,预期仅返回资源ID字符串,实际返回了体积很大的完整对象结构,不符合预期。
问题根因与修复方案

问题1:响应头格式错误+枚举逻辑错误

Content-Type是HTTP标准头,格式要求为MIME类型; 参数键=参数值,MIME类型和charset参数之间必须用分号分隔,不能使用逗号。
现有代码列表分支存在两个明确错误:

  • 用逗号分隔text/html和charset=utf-8,直接触发头格式校验异常
  • 返回JSON结构时误用text/html作为MIME类型,JSON对应的标准MIME类型是application/json

额外注意两个细节:

  • WriteAsJsonAsync方法运行时会自动写入正确的application/json; charset=utf-8头,不需要手动添加该头,避免重复设置或格式写错
  • ResourceGroupCollection是SDK返回的异步分页集合AsyncPageable<ResourceGroupResource>,不能直接用同步foreach遍历,必须用await foreach做异步枚举,否则会出现枚举异常

问题2:序列化对象类型错误

resourceGroup.Data.Id是Azure SDK封装的ResourceIdentifier复杂类型,不是原生字符串。直接把这个对象传给JsonSerializer.Serialize时,序列化器会递归序列化该类型的所有公共属性,最终输出完整的大对象结构。如果只需要返回资源ID字符串,直接调用ResourceIdentifier.ToString()拿到ID的字符串表现形式即可,不需要序列化整个复杂对象。
另外单资源组分支中resourceGroup = await resourceGroup.GetAsync();属于冗余代码,resourceGroups.GetAsync(rg)已经返回了目标资源组实例,重复调用GetAsync会发起一次不必要的Azure管理API请求,可以直接删除。

修正后的完整代码
[Function("getRg")]
public async Task<HttpResponseData> GetRgs([HttpTrigger(AuthorizationLevel.Function, "get", Route = "rg")] HttpRequestData req,
        string? rg, string sub,
        FunctionContext functionContext)
{
    ArmClient client = new ArmClient(new DefaultAzureCredential());

    SubscriptionCollection subscriptions = client.GetSubscriptions();
    SubscriptionResource subscription = await subscriptions.GetAsync(sub);

    ResourceGroupCollection resourceGroups = subscription.GetResourceGroups();

    if (!string.IsNullOrEmpty(rg))
    {
        ResourceGroupResource resourceGroup = await resourceGroups.GetAsync(rg);
        // 直接取资源ID的字符串形式,避免序列化复杂对象
        string rgId = resourceGroup.Data.Id.ToString();

        _logger.LogInformation($"requested RG: {rgId}");

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString(rgId);

        return response;
    }
    else 
    {
        var rgList = new List<string>();
        // 异步分页集合必须用await foreach遍历
        await foreach (var rgItem in resourceGroups)
        {
            rgList.Add(rgItem.Data.Name);
        }

        _logger.LogInformation($"rg list: {rgList}");

        var response = req.CreateResponse(HttpStatusCode.OK);
        // WriteAsJsonAsync自动设置正确的Content-Type,无需手动添加
        await response.WriteAsJsonAsync(rgList);

        return response;
    }
}

内容的提问来源于stack exchange,提问作者Renm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:24:18