为什么我的Azure移动应用不会返回任何数据?

时间:2017-02-28 14:01:18

标签: c# azure xamarin azure-mobile-services

我一直在关注Azure移动应用程序和简易表格(https://blog.xamarin.com/getting-started-azure-mobile-apps-easy-tables/)的教程。一切都进行得很顺利,我设法到了测试我的应用程序的点,似乎没有返回任何数据,我不知道为什么,我也没有收到任何错误正在使这个问题的追踪更加困难。

好的开始我拥有我的Azure数据库(配置为允许访问Azure服务)并且我创建了我的表并使用EasyTables工作。我使用Postman(https://www.getpostman.com/)应用程序来测试我的API并确保使用https://myproject.azurewebsites.net/tables/users从我的数据库返回数据,该数据以json的形式返回我的数据。

我的数据库表名为users,其结构非常基础(用于测试),包含两列idFirstName。我已经用虚拟数据填充了我的表格,我已经证明可以使用Postman从我的azure uri返回。

这是开始运行的基础工作,这是我的项目层次结构的快照。

enter image description here

MyProject的/型号/ users.cs

这是实体数据,其名称与数据库中的表匹配。

using System;
using Microsoft.WindowsAzure.MobileServices;
using Newtonsoft.Json;

namespace MyProject
{
    public class users
    {

        [JsonProperty(PropertyName = "Id")]
        public string id { get; set; }       

        public string FirstName {get; set; }
    }
}

MyProject的/服务/ AzureService.cs

至关重要的是,我们在此处执行public async Task<IEnumerable<users>> GetUsers()任务,并触发Inialization任务(这是定义应用网址的位置)。

using System;
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.Sync;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using System.Diagnostics;
using Xamarin.Forms;
using MyProject;
using System.IO;
using Plugin.Connectivity;

[assembly: Dependency(typeof(AzureService))]
namespace MyProject
{
    public class AzureService
    {
        public MobileServiceClient Client { get; set; } = null;

        IMobileServiceSyncTable<users> userTable;       
        public async Task Initialize()
        {
            if (Client?.SyncContext?.IsInitialized ?? false)
                return;

            var appUrl = "https://myproject.azurewebsites.net";

            //Create our client

            Client = new MobileServiceClient(appUrl);


            //InitialzeDatabase for path
            var path = "syncstore.db";
            //path = Path.Combine(MobileServiceClient.DefaultDatabasePath, path);

            //setup our local sqlite store and intialize our table
            var store = new MobileServiceSQLiteStore(path);

            //Define table
            store.DefineTable<users>();


            //Initialize SyncContext
            await Client.SyncContext.InitializeAsync(store);

            //Get our sync table that will call out to azure
            userTable = Client.GetSyncTable<users>();


        }

        public async Task SyncUsers()
        {
            try
            {

                await userTable.PullAsync("allUsers", userTable.CreateQuery());

                await Client.SyncContext.PushAsync();
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Unable to sync users, that is alright as we have offline capabilities: " + ex);
            }

        }

        //
        //Get Users
        public async Task<IEnumerable<users>> GetUsers()
        {
            await Initialize();
            await SyncUsers();

            return await userTable.ToEnumerableAsync(); ;

        }   
    }
}

MyProject的/视图/ UserList.xaml

为了测试的目的,我保持简短和简约。一个简单的列表,它的源设置为UsersList(它是ViewModel中的Observable集合)。列表中的每个项目都绑定到FirstName

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyProject;assembly=MyProject"
             x:Class="MyProject.UserList"
             Title="UserList">
        <ListView x:Name="userList"
                  ItemsSource="{Binding UsersList}"
                  IsRefreshing="{Binding IsBusy, Mode=OneWay}"
                  RefreshCommand="{Binding LoadUsersCommand}"
                  Grid.Row="1">
            <ListView.ItemTemplate>
                <DataTemplate>
                <ViewCell>
                    <StackLayout HorizontalOptions="StartAndExpand" Orientation="Horizontal" Padding="15,5,0,0">
                            <StackLayout Padding="5,0,0,0" VerticalOptions="StartAndExpand" Orientation="Vertical">
                            <Label Text="{Binding FirstName}"  />
                        </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>        
</ContentPage>

MyProject的/视图/ UserList.xaml.cs

这只是说明UserList绑定到viewmodel,当列表出现时会从viewmodel中触发load users命令。

using System;
using System.Collections.Generic;
using Plugin.Connectivity;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace MyProject
{
    public partial class UserList : ContentPage
    {
        UsersViewModel vm;

        public UserList()
        {
            InitializeComponent();
            BindingContext = vm = new UsersViewModel();
        }

        protected override async void OnAppearing()
        {
            base.OnAppearing();

            vm.LoadUsersCommand.Execute(null);            
        }       
    }
}

MyProject的/视图模型/ UsersViewModel.cs

此文件功能最多,视图模型具有可观察的定义和加载用户命令。

using System;
using MvvmHelpers;
using System.Windows.Input;
using System.Threading.Tasks;
using System.Diagnostics;
using Xamarin.Forms;
using System.Linq;
using Microsoft.WindowsAzure.MobileServices;

namespace MyProject
{
    public class UsersViewModel : BaseViewModel
    {
        AzureService azureService;
        public UsersViewModel()
        {
            azureService = DependencyService.Get<AzureService>();
        }

        public ObservableRangeCollection<users> UserList { get; } = new ObservableRangeCollection<users>();

        string loadingMessage;
        public string LoadingMessage
        {
            get { return loadingMessage; }
            set { SetProperty(ref loadingMessage, value); }
        }

        ICommand  loadUsersCommand;
        public ICommand LoadUsersCommand =>
            loadUsersCommand ?? (loadUsersCommand = new Command(async () => await ExecuteLoadUsersCommandAsync())); 

        async Task ExecuteLoadUsersCommandAsync()
        {
            try 
            {                
                LoadingMessage = "Loading Users...";
                IsBusy = true;
                var users = await azureService.GetUsers();
                UserList.ReplaceRange(users);
            }
            catch (Exception ex) 
            {
                Debug.WriteLine("OH NO!" + ex);

                await Application.Current.MainPage.DisplayAlert("Sync Error", "Unable to sync users, you may be offline", "OK");
            } 
            finally 
            {
                IsBusy = false;
            }
        }     
    }
}

我在运行应用程序时突然出现了几个断点,看看我是否可以找到问题的根源,缺少错误意味着我没有参考框架可供使用。

事件触发的当前顺序如下(基于我输入的断点):

  1. public ObservableRangeCollection<users> UserList { get; } = new ObservableRangeCollection<users>(); - UserViewModel
  2. azureService = DependencyService.Get<AzureService>(); - UserViewModel
  3. var users = await azureService.GetUsers(); - UserViewModel
  4. await Initialize(); - AzureService
  5. public async Task Initialize() - AzureService
  6. await SyncUsers(); - AzureServce
  7. public async Task SyncUsers() - AzureService
  8. return await userTable.ToEnumerableAsync(); ; - AzureService
  9. UserList.ReplaceRange(users); - UserViewModel
  10. 然后使用模拟器将列表加载到我的MacBook Pro上,但它是空的,根本没有数据。任何人都可以帮助我理解为什么我无法获取我的数据?他们的断点是否应该到位并检查某些物品是否存在?

    就像我说没有实际错误这是一个艰难的错误,但它也可能是非常简单的,任何帮助都是值得赞赏的。

    更新

    在我的初步调查之后,我已在我的代码中添加了if语句,特别是在OnAppearing中的UserList.xaml.cs方法中。我在UserList中添加UserViewModel.cs集合的代码检查的代码是否为0。

     protected override async void OnAppearing()
     {
         base.OnAppearing();
    
         if (vm.UserList.Count == 0)
             vm.LoadUsersCommand.Execute(null);
         else
         {
             ...
         }
         vm.LoadUsersCommand.Execute(null);
     }
    

    有趣的是,UserList总是以0返回。所以问题看起来就像UsersViewModel.cs

    中的这行代码一样

    public ObservableRangeCollection<users> UserList { get; } = new ObservableRangeCollection<users>();

    导致这种情况的原因是什么?

1 个答案:

答案 0 :(得分:0)

我唯一能看到的是你将id列重命名为Id - 在客户端上,它需要是id(小写)。

还有其他一些错误,但应该很容易找到调试器。我看到其中一个已被指出。