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)
{
...
...
}
Любая альтернатива этому может быть?
Ответы
Ответ 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.
- Добавьте 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 не смешиваются:)