【问题标题】:System.NotSupportedException when trying to create an asset尝试创建资产时出现 System.NotSupportedException
【发布时间】:2015-08-13 17:22:54
【问题描述】:

我正在尝试在Azure 中托管的API Service 中使用Azure MediaService APIAzure Storage API

用户将视频流以HttpPost 的形式发送到服务,服务将视频作为 blob 保存在我的存储帐户中,媒体服务对视频进行编码,当视频链接准备就绪时,它会返回到用户。

但是当我尝试创建 Asset 时,会抛出 System.NotSupportedException 并显示以下消息:

抛出异常:Microsoft.Data.Services.Client.dll 中的“System.NotSupportedException” 抛出异常:mscorlib.dll 中的“System.NotSupportedException” iisexpress.exe 错误:0:异常=System.NotSupportedException:这 目标框架不允许您直接枚举数据 服务查询。这是因为枚举会自动发送一个 对数据服务的同步请求。因为这个框架只有 支持异步操作,您必须改为调用 BeginExecute 和 EndExecute 方法获取支持枚举的查询结果。

我正在使用以下版本的所需依赖项:

Microsoft.Data.Services.Client - 5.6.2.0
Microsoft.WindowsAzure.MediaServices.Client - 3.0.0.8
Microsoft.WindowsAzure.Storage - 3.1.0.1

这是我的代码:

CloudMediaContext _context;
IAsset asset;
using (MemoryStream Ms = new MemoryStream(data.Data))
{
    _context = new CloudMediaContext("accountName", "accountKey");
    asset = await _context.Assets.CreateAsync("blobContainerName",
        AssetCreationOptions.None,CancellationToken.None);
    ...
    ...
}

data.Data 包含视频的byte[]。调用CreateAsync 时会引发异常。我尝试了_context.Assets.Create,但没有成功。

重要编辑

我创建了一个新的控制台应用程序,使用了我在 API 服务中使用的代码,它已成功执行。所以问题出在 API 服务上。

这是我的类和方法定义

public class UploadController : ApiController
{

    [HttpPost]
    public async Task<string> PostUpload(VideoData data)
    {
        ...
        ...
    }

可能有其他选择吗?

【问题讨论】:

  • 嘿,我不确定 'await' 是否在使用中。你看azure.microsoft.com/de-de/documentation/articles/…了吗?
  • 您好,感谢您的评论!我尝试了Create 而不是CreateAsync,但没有成功。
  • 看来Create(Async)背后有一堆操作,不妨看看CreateEmptyAsset:blog-ndrouin.azurewebsites.net/creating-a-simple-media-asset
  • CreateEmptyAsset 不再存在。 Create 或 CreateAsync 是现在创建空资产的方法。还是谢谢!
  • 我认为 CreateAsync 可能需要一个唯一的 id?根据文档here,他们为文件创建了一个唯一标识符。也许通过设置 AssetCreationOptions.None,您正在尝试创建一个已经存在的文件。

标签: c# azure async-await azure-blob-storage azure-media-services


【解决方案1】:

我不能告诉你为什么它不能正常工作。 但我认为问题更可能出现在函数的构造中,而不是在 Azure API 中。

应该这样做:

    // Important is the return value of the function: 
    public async Task<IAsset> CreateAssetBlobAsync(CancellationToken token)
    {            
        var asset = await _context.Assets.CreateAsync("blobContainerName", AssetCreationOptions.None, CancellationToken.None); // or your 'token'

        return asset;
    }

这个异步函数应该这样调用:

public static async Task ProcessNewBlobAsync()
{
     // ...

     var asset = await CreateAssetBlobAsync(token);

     // ...
}

我认为问题出在你的using 声明

事实上,MemoryStreamRead/Write Async 方法实际上并没有提供任何真正的异步实现。这意味着它们将始终是同步的。

(但是你没有调用它们中的任何一个。我担心它可能是异步方法的同步包装器。所以它会调用 API 同步而不是异步。这只是一个想。)

我建议避免使用带有async 的语句用于preventing a deadlock


【讨论】:

  • 我看不出我的代码有什么不同,但我试过了,还是不行!不过感谢您的回答。
  • 哇哈哈!我想解决这个问题。你能再贴一些代码吗?
  • 完成。不幸的是,没有什么可显示的,因为调用 CreateAsync 时会引发异常。感谢您的帮助!
  • @GeorgeChond:更新后,请检查代码是否在using声明之外工作。
  • 这毫无意义。他为什么要调用async 方法synchronously。必须有东西包裹整个东西。有什么可能导致这种行为吗?
【解决方案2】:

我希望“blobContainerName”是您在发布问题时写的一个模拟?大写字母和 blob 容器不能混用 :)

【讨论】:

  • 当我使用普通控制台应用程序时它正在工作,所以我认为问题不在于 blob 容器的名称。谢谢!
  • 这很有趣,如果我在容器名称中包含大写字母,它总是会导致异常。
【解决方案3】:

你能不能尝试调用方法

Task<IAsset> CreateAsync(string assetName, string storageAccountName, AssetCreationOptions options, CancellationToken cancellationToken)

并传递与媒体服务关联的默认存储帐户名称。在您的示例中,您正在调用查询默认存储帐户名称的方法。存储帐户的查询没有异步完成,这是一个错误。此存储帐户查询在每个上下文中发生一次,不会在服务器上产生负载。如果您可以在应用初始化期间查询并稍后在创建资产调用中使用它,那就太好了。

【讨论】:

    【解决方案4】:

    我能够使用 .NET 4.6.1 和以下 nuget 包创建一个工作演示:

    [HttpPost]
    public async Task<string> PostUpload()
    {
        var bytes = System.Text.Encoding.UTF8.GetBytes("Test");
        var data = new VideoData { Data = bytes };
        CloudMediaContext _context;
        using (MemoryStream ms = new MemoryStream(data.Data))
        {
            var accountName = "accountName";
            var accountKey = @"primaryaccessKey";
            _context = new CloudMediaContext(accountName, accountKey);
            var asset = await _context.Assets.CreateAsync("myjblobassets", AssetCreationOptions.None, CancellationToken.None);
            //... do something with asset and ms ...
        }
        return "http://my-link";
    }
    

    * 注意:这里的任何字节都可以,因为我们没有演示上传部分,我们确保创建媒体服务资产有效。

    1. 添加 HTML form 并在 index 视图中提交 button 指向此发布操作,运行它并运行!!!

    注意:在 NAME 中,输入新帐户的名称。媒体服务帐户名称全部为小写数字或字母,不带空格,长度为 3 - 24 个字符。 https://azure.microsoft.com/en-us/documentation/articles/media-services-dotnet-get-started/

    【讨论】:

      最近更新 更多