(Не найдено) Ошибка в бэкэнде мобильных служб Azure.NET
Застрял с этой ошибкой до фазы безумия... Пожалуйста, помогите
Я создал серверную часть Azure Mobile Service .NET и сейчас пытаюсь вызвать функцию Post из клиента Xamarin Android.
Я инициализирую и вызываю асинхронную функцию Вставки (это всего лишь фрагменты из моего кода)
private static IMobileServiceTable<Todo> _todoMobileServiceTable;
public static bool? InitializeAms()
{
try
{
CurrentPlatform.Init();
_mobileServiceClient = new MobileServiceClient(applicationUrl, applicationKey);
_todoMobileServiceTable = _mobileServiceClient.GetTable<Todo>();
return true;
}
catch (MalformedURLException malformedUrlException)
{
ReportHelper.Report(Tag, "There was an error creating the Mobile Service. Verify the URL", true, malformedUrlException);
}
catch (Exception exception)
{
ReportHelper.Report(Tag, "Error occurred during initialization of Azure Mobile Services", true, exception);
}
return null;
}
_todoMobileServiceTable.InsertAsync(Todo);
Я получаю следующую ошибку при вызове.InsertAsync(Todo)
Запрос не может быть завершен. (Не обнаружена)
NB:
Клиент хранилища Azure пока недоступен для xamarin, и у меня нет другого выбора, кроме как использовать этот грязный форк, которому 1 год, и который создан для iOS, а не для Android (хотя он отлично работает с javascript мобильного сервиса Azure) https://github.com/zgramana/IOSAzureBlobUploader
Он работает, если я использую кнопку "попробовать" в браузере, но не работает, когда я вызываю его из клиентского приложения xamarin.
Он работает из клиентского приложения xamarin, если я использую мобильный сервис javascript
Эта ошибка возникает как в локальном мобильном сервисе Azure, так и в опубликованном онлайн.
Вот класс WebApiConfig
namespace Service.Ams
{
public static class WebApiConfig
{
public static void Register()
{
// Use this class to set configuration options for your mobile service
ConfigOptions options = new ConfigOptions();
// Use this class to set WebAPI configuration options
HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));
// To display errors in the browser during development, uncomment the following
// line. Comment it out again when you deploy your service for production use.
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
Database.SetInitializer(new ServiceAmsInitializer());
}
}
public class ServiceAmsInitializer : ClearDatabaseSchemaIfModelChanges<ServiceAmsDbContext>
{}
}
Вот класс TableController
namespace Service.Ams.Controllers
{
public class TodoItemController : TableController<TodoItem>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
ServiceAmsDbContext serviceAmsDbContext = new ServiceAmsDbContext();
DomainManager = new EntityDomainManager<TodoItem>(serviceAmsDbContext, Request, Services);
}
// GET tables/TodoItem
[AuthorizeLevel(AuthorizationLevel.Admin)]
public IQueryable<TodoItem> GetAllTodoItems()
{
return Query();
}
// GET tables/TodoItem/55D11C86-6EA6-4C44-AA33-337FC9A27525
[AuthorizeLevel(AuthorizationLevel.Admin)]
public SingleResult<TodoItem> GetTodoItem(string id)
{
return Lookup(id);
}
// PATCH tables/TodoItem/55D11C86-6EA6-4C44-AA33-337FC9A27525
[AuthorizeLevel(AuthorizationLevel.Admin)]
public Task<TodoItem> PatchTodoItem(string id, Delta<TodoItem> patch)
{
return UpdateAsync(id, patch);
}
// POST tables/TodoItem/55D11C86-6EA6-4C44-AA33-337FC9A27525
[AuthorizeLevel(AuthorizationLevel.Anonymous)]
public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
{
string storageAccountName;
string storageAccountKey;
// Try to get the Azure storage account token from app settings.
if (
!(Services.Settings.TryGetValue("STORAGE_ACCOUNT_NAME", out storageAccountName) |
Services.Settings.TryGetValue("STORAGE_ACCOUNT_ACCESS_KEY", out storageAccountKey)))
Services.Log.Error("Could not retrieve storage account settings.");
// Set the URI for the Blob Storage service.
Uri blobEndpoint = new Uri(string.Format("http://127.0.0.1:10000/{0}/", storageAccountName));
// Create the BLOB service client.
CloudBlobClient blobClient = new CloudBlobClient(blobEndpoint, new StorageCredentials(storageAccountName, storageAccountKey));
// Create a container, if it doesn't already exist.
CloudBlobContainer container = blobClient.GetContainerReference(item.ContainerName);
await container.CreateIfNotExistsAsync();
// Create a shared access permission policy.
BlobContainerPermissions containerPermissions = new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
};
// Enable anonymous read access to BLOBs.
container.SetPermissions(containerPermissions);
// Define a policy that gives write access to the container for 5 minutes.
SharedAccessBlobPolicy sasPolicy = new SharedAccessBlobPolicy
{
SharedAccessStartTime = DateTime.UtcNow,
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(5),
Permissions = SharedAccessBlobPermissions.Write
};
// Get the SAS as a string.
item.SasQueryString = container.GetSharedAccessSignature(sasPolicy);
// Set the URL used to store the image.
item.ImageLqUri = string.Format("{0}{1}/{2}", blobEndpoint, item.ContainerName, item.ResourceNameLq);
item.ImageHqUri = string.Format("{0}{1}/{2}", blobEndpoint, item.ContainerName, item.ResourceNameHq);
// Complete the insert operation.
TodoItem current = await InsertAsync(item);
return CreatedAtRoute("Tables", new {id = current.Id}, current);
}
// DELETE tables/TodoItem/55D11C86-6EA6-4C44-AA33-337FC9A27525
[AuthorizeLevel(AuthorizationLevel.Admin)]
public Task DeleteTodoItem(string id)
{
return DeleteAsync(id);
}
}
}
Вот класс EntityData
namespace Service.Ams.DataObjects
{
[Table("dbo.TodoItems")]
public class TodoItem : EntityData
{
public string ContainerName { get; set; }
public string ResourceNameLq { get; set; }
public string ResourceNameHq { get; set; }
public string SasQueryString { get; set; }
public string ImageLqUri { get; set; }
public string ImageHqUri { get; set; }
}
}
2 ответа
Есть ли способ получить дамп того, как выглядит HTTP-запрос?
У меня нет под рукой Android-клиента, но мы можем посмотреть в понедельник.
Хенрик
TableController и соответствующий клиенту класс должны иметь одинаковые имена, например TodoController и TodoClass. Я не знаю, есть ли атрибут, который изменяет это правило и как его использовать, если на стороне сервера, украшающей класс TableController, или на стороне клиента, украшающей класс данных.