使用.NET库创建Azure Media Services定位器失败问题排查
问题描述
此前正常运行的旧版V2 Azure Media Services账号,使用.NET代码创建Streaming Locator时抛出无额外详情的BadRequest异常。代码如下:
var contentKeys = new List<StreamingLocatorContentKey> { new StreamingLocatorContentKey( contentKeyId, StreamingLocatorContentKeyType.CommonEncryptionCenc, "cencKeyDefault", Convert.ToBase64String(contentKeyValue)) }; return await mClient.StreamingLocators.CreateAsync( mResourceGroupName, mAccountName, locatorName, new StreamingLocator(assetName, PredefinedStreamingPolicy.MultiDrmCencStreaming, defaultContentKeyPolicyName: "KeyPolicy", contentKeys: contentKeys));
其中locatorName为$"Locator-{contentKeyId:N}"。
经测试:
- 新建V2或V3账号均出现相同问题;
- 移除
contentKeys: contentKeys参数后代码可正常运行,但业务需要传递密钥值,因此该方案不可行,说明问题出在密钥相关请求部分; - 使用如下POST请求可成功创建:
POST https://management.azure.com/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroup}}/providers/Microsoft.Media/mediaServices/{{msName}}/streamingLocators/Locator-A1?api-version=2021-11-01 { "properties": { "assetName": "Video-A1", "streamingPolicyName": "Predefined_MultiDrmCencStreaming", "defaultContentKeyPolicyName": "KeyPolicy", "contentKeys": [ { "labelReferenceInStreamingPolicy": "cencKeyDefault", "id": "60000000-0000-0000-0000-000000000001", "value": "1UqLohAfWsEGkULYxHjYZg==" }] } }
环境信息:
- 项目:.NET 6
- Microsoft.Azure.Common: 2.2.1
- Microsoft.Azure.Management.Media: 6.0.0
- Microsoft.Azure.Storage.Blob: 11.2.3
- Microsoft.Rest.ClientRuntime.Azure.Authentication: 2.4.1
需解决两个问题:
- 代码中存在什么问题?
- 如何调试Azure调用以获取详细错误信息,而非仅BadRequest状态码?
附:官方文档中错误提及cencDefaultKey,实际需使用cencKeyDefault才能正常运行。
问题解答
一、代码中的核心问题
对比成功的POST请求与.NET代码的差异,问题出在StreamingLocatorContentKey的参数赋值逻辑上:
.NET SDK的StreamingLocatorContentKey构造函数中,第三个参数对应**Label**属性,但Azure服务实际需要的是将"cencKeyDefault"赋值给LabelReferenceInStreamingPolicy属性。你当前的代码把值传给了Label字段,导致请求体中的字段与服务端期望不匹配,触发BadRequest。
修改后的正确代码如下:
var contentKeys = new List<StreamingLocatorContentKey> { new StreamingLocatorContentKey { Id = contentKeyId, Type = StreamingLocatorContentKeyType.CommonEncryptionCenc, LabelReferenceInStreamingPolicy = "cencKeyDefault", Value = Convert.ToBase64String(contentKeyValue) } }; return await mClient.StreamingLocators.CreateAsync( mResourceGroupName, mAccountName, locatorName, new StreamingLocator(assetName, PredefinedStreamingPolicy.MultiDrmCencStreaming, defaultContentKeyPolicyName: "KeyPolicy", contentKeys: contentKeys));
二、获取详细错误信息的调试方法
1. 捕获CloudException解析详细错误
Azure SDK抛出的CloudException包含服务返回的完整错误细节,通过try-catch捕获并输出:
try { return await mClient.StreamingLocators.CreateAsync(...); } catch (CloudException ex) { Console.WriteLine($"错误代码: {ex.Error.Code}"); Console.WriteLine($"错误消息: {ex.Error.Message}"); Console.WriteLine($"响应内容: {ex.Response.Content}"); throw; }
2. 启用HTTP请求日志记录
通过自定义日志处理器,查看SDK实际发送的请求体和响应内容,对比手动成功的POST请求定位差异:
// 自定义日志处理器 public class LoggingHandler : DelegatingHandler { private readonly ILogger _logger; public LoggingHandler(HttpMessageHandler innerHandler, ILogger logger) : base(innerHandler) { _logger = logger; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // 记录请求信息 _logger.LogInformation($"请求方法: {request.Method}, URL: {request.RequestUri}"); if (request.Content != null) { var content = await request.Content.ReadAsStringAsync(cancellationToken); _logger.LogInformation($"请求体: {content}"); } var response = await base.SendAsync(request, cancellationToken); // 记录响应信息 _logger.LogInformation($"响应状态码: {response.StatusCode}"); if (response.Content != null) { var content = await response.Content.ReadAsStringAsync(cancellationToken); _logger.LogInformation($"响应体: {content}"); } return response; } } // 实现简单的控制台日志 public interface ILogger { void LogInformation(string message); } public class ConsoleLogger : ILogger { public void LogInformation(string message) { Console.WriteLine(message); } }
初始化客户端时使用该处理器:
var handler = new HttpClientHandler(); var logger = new ConsoleLogger(); var httpClient = new HttpClient(new LoggingHandler(handler, logger)); var credentials = await GetCredentialsAsync(); // 替换为你的认证逻辑 mClient = new AzureMediaServicesClient(httpClient, credentials) { SubscriptionId = subscriptionId };
3. 查看Azure Monitor服务端日志
在Azure门户进入你的Media Services账号,依次点击监控 > 日志,查询操作日志即可看到服务端返回的完整错误详情。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

