Подтвердить что ты не робот

System.NotSupportedException при попытке создания актива

Я пытаюсь использовать Azure MediaService API вместе с Azure Storage API в API Service, размещенном в Azure.

Пользователь отправляет видеопоток службе в качестве HttpPost, служба сохраняет видео как blob в моей учетной записи Storage, медиасервер кодирует видео и когда ссылка на видео готова, она возвращается пользователя.

Но когда я пытаюсь создать Asset a System.NotSupportedException, выдается с сообщением:

Исключение выбрано: "System.NotSupportedException" в Microsoft.Data.Services.Client.dll Исключение: "System.NotSupportedException" в файле mscorlib.dll Ошибка 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)
    {
        ...
        ...
    }

Любая альтернатива этому может быть?

4b9b3361

Ответ 1

Мне удалось создать рабочую демонстрацию, используя .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";
}

* Примечание: любые байты здесь прекрасны, так как мы не показываем загружаемую часть, мы делаем все возможное, чтобы создать Media Service Asset.

  1. Добавьте HTML form и отправьте button в индексный вид, указывающий на это действие post, запустите его и заработайте!!!

введите описание изображения здесь

Примечание: В поле NAME введите имя новой учетной записи. Имя учетной записи Media Services - это все строчные буквы или буквы без пробелов и длина 3-24 символа. https://azure.microsoft.com/en-us/documentation/articles/media-services-dotnet-get-started/

Ответ 2

Я не могу сказать, почему он не работает точно. Но я думаю, что проблема с большей вероятностью найдет в построении вашей функции, чем в 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.

Факт - это методы Read/Write Async MemoryStream, фактически не предоставляют какой-либо истинной асинхронной реализации. Это означает, что они всегда будут синхронно.

(Но вы не вызывали никого из них. Я боюсь, что это будет синхронная оболочка для асинхронного метода, и поэтому он будет вызывать синхронный API вместо асинхронного. Это только мысль.)

Я рекомендую избегать использования выражений с async для предотвращения тупика.


Ответ 3

Можете ли вы попытаться вызвать метод

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

и передать имя учетной записи хранилища по умолчанию, связанную со службой мультимедиа. В вашем примере вы вызываете метод, который запрашивает имя учетной записи хранилища по умолчанию. Запрос учетной записи хранилища выполнен не асинхронно, и это ошибка. Этот запрос учетной записи хранилища выполняется один раз для контекста, чтобы не генерировать нагрузку на сервер. Будет полезно, если вы сможете запросить во время инициализации приложения и использовать его в своих вызовах создания ресурса позже.

Ответ 4

Я надеюсь, что "blobContainerName" - это макет, который вы написали при публикации вопроса? Заглавные буквы и контейнеры blob не смешиваются:)