Scope
The following article covers a presentation and demo, presented at Xamarin Dev Days in Mauritius. The article demonstrates how to get started with Azure Mobile Apps and get the benefit of the powers of the cloud in terms of Scalability, Offline Sync, and Data Analytics.
This is the second part of the series where we’ll extend the sample app, discussed in part one.
Introduction
The objective of this article is to build a sample app discussed in part 1 and add custom logic. In this demo, an app, that will allow the attendees of Xamarin Dev Days to give feedback to the organizers, will be created. The application will store the attendee name, the attendee feedback, and a sentiment score.
Modifying the Cloud Back-end
- Adding the Data Object
The first step is to add the data object. Therefore, create a new file called Feedback.cs in the DataObjects folder.
Make sure that the class inherits from EntityData from "Microsoft.Azure.Mobile.Server", and add the attributes of the model, as below.
- public class Feedback: EntityData {
- public string Name {
- get;
- set;
- }
- public string FeedbackText {
- get;
- set;
- }
- public double SentimentScore {
- get;
- set;
- }
- }
- Adding the Controller
In the controller, the following methods will need to be added.
Luckily, with the Microsoft Azure SDK, all the codes do not have to be typed from scratch. Instead, scaffolding can be used. Please follow the steps below to scaffold the codes for the controller.
- Right-click on the Controller folder and click Add > Controller.
- Select Azure Table App Controller and click Add.
- Select the Model, Context, and click Add.
- The following code will be automatically generated.
- public class FeedbackController: TableController < Feedback > {
- protected override void Initialize(HttpControllerContext controllerContext) {
- base.Initialize(controllerContext);
- devdaysblogContext context = new devdaysblogContext();
- DomainManager = new EntityDomainManager < Feedback > (context, Request);
- }
-
-
- public IQueryable < Feedback > GetAllFeedback() {
- return Query();
- }
-
-
- public SingleResult < Feedback > GetFeedback(string id) {
- return Lookup(id);
- }
-
-
- public Task < Feedback > PatchFeedback(string id, Delta < Feedback > patch) {
- return UpdateAsync(id, patch);
- }
-
-
- public async Task < IHttpActionResult > PostFeedback(Feedback item) {
- Feedback current = await InsertAsync(item);
- return CreatedAtRoute("Tables", new {
- id = current.Id
- }, current);
- }
-
-
- public Task DeleteFeedback(string id) {
- return DeleteAsync(id);
- }
- }
- Add the migrations
Since the code first approach is used here, code first migrations will need to be added to the project. Follow the steps here to get started with the migrations.
- Now that our back-end code is ready, we can deploy it to Azure App Service.
Modifying the Client App
In the portable class library, add the following.
- Feedback.cs class
Add the properties that will be required to capture the feedback, the property ID to uniquely identify each record, and the property version which will be used internally by Azure App Service to keep track of which version of the record is being modified.
- public class Feedback {
- string id;
- string name;
- string feedbacktext;
- double sentimentscore;
-
- [JsonProperty(PropertyName = "id")]
- public string Id {
- get {
- return id;
- }
- set {
- id = value;
- }
- }
- [JsonProperty(PropertyName = "Name")]
- public string Name {
- get {
- return name;
- }
- set {
- name = value;
- }
- }
- [JsonProperty(PropertyName = "FeedbackText")]
- public string FeedbackText {
- get {
- return feedbacktext;
- }
- set {
- feedbacktext = value;
- }
- }
- [JsonProperty(PropertyName = "SentimentScore")]
- public double SentimentScore {
- get {
- return sentimentscore;
- }
- set {
- sentimentscore = value;
- }
- }
-
- [Version]
- public string Version {
- get;
- set;
- }
- }
- Add the class FeedbackManager.cs with the following variables and methods.
-
- static FeedbackManager defaultInstance = new FeedbackManager();
-
- MobileServiceClient client;
-
- IMobileServiceTable < Feedback > feedbackTable;
-
- private FeedbackManager() {
- this.client = new MobileServiceClient(Constants.ApplicationURL);
- this.feedbackTable = client.GetTable < Feedback > ();
- }
-
- public static FeedbackManager DefaultManager {
- get {
- return defaultInstance;
- }
- private set {
- defaultInstance = value;
- }
- }
-
- public MobileServiceClient CurrentClient {
- get {
- return client;
- }
- }
-
- public async Task < ObservableCollection < Feedback >> GetFeedbacksAsync(bool syncItems = false) {
- try {
- IEnumerable < Feedback > items = await feedbackTable.ToEnumerableAsync();
- return new ObservableCollection < Feedback > (items);
- } catch (MobileServiceInvalidOperationException msioe) {
- Debug.WriteLine(@ "Invalid sync operation: {0}", msioe.Message);
- } catch (Exception e) {
- Debug.WriteLine(@ "Sync error: {0}", e.Message);
- }
- return null;
- }
-
- public async Task SaveFeedbackAsync(Feedback item) {
- if (item.Id == null) {
- await feedbackTable.InsertAsync(item);
- } else {
- await feedbackTable.UpdateAsync(item);
- }
- }
- Add the Feedback Page
- XAML Snippet
The XAML codes has 3 main parts, namely, the TextBoxes (Entry), the Add button, and a list view.
- <StackLayout Orientation="Vertical">
- <Entry x:Name="newItemName" Placeholder="Enter your name" />
- <Entry x:Name="newFeedbackText" Placeholder="Enter your feedback" /> </StackLayout>
- <Button Text="Save" MinimumHeightRequest="30" Clicked="OnAdd" />
- <ListView x:Name="todoList" IsPullToRefreshEnabled="true" Refreshing="OnRefresh" Grid.Row="1">
- <ListView.ItemTemplate>
- <DataTemplate>
- <ViewCell>
- <StackLayout Orientation="Horizontal" HeightRequest="30">
- <Label Text="{Binding Name}" />
- <Label Text="{Binding FeedbackText}" /> </StackLayout>
- </ViewCell>
- </DataTemplate>
- </ListView.ItemTemplate>
- </ListView>
- The Feedback.xaml.cs code
The following methods interact with the Manager Class to add and retrieve the feedback.
- async Task AddItem(Feedback item) {
- await manager.SaveFeedbackAsync(item);
- todoList.ItemsSource = await manager.GetFeedbacksAsync();
- }
- private async Task RefreshItems(bool showActivityIndicator, bool syncItems) {
- todoList.ItemsSource = await manager.GetFeedbacksAsync(syncItems);
- }
The following code handles the events generated by the application.
- public async void OnAdd(object sender, EventArgs e) {
- var feedback = new Feedback {
- Name = newItemName.Text,
- FeedbackText = newFeedbackText.Text
- };
- await AddItem(feedback);
- newItemName.Text = string.Empty;
- newItemName.Unfocus();
- }
- public async void OnRefresh(object sender, EventArgs e) {
- var list = (ListView) sender;
- Exception error = null;
- try {
- await RefreshItems(false, true);
- } catch (Exception ex) {
- error = ex;
- } finally {
- list.EndRefresh();
- }
- if (error != null) {
- await DisplayAlert("Refresh Error", "Couldn't refresh data (" + error.Message + ")", "OK");
- }
- }
- public async void OnSyncItems(object sender, EventArgs e) {
- await RefreshItems(true, true);
- }
- The last part is to modify the App.cs page to launch the Feedback page by default when the app launches.
MainPage = new FeedbackPage();
- Run the application and test.
You can also verify in the database. The Feedback table will be created and the new record will be inserted.
Conclusion
In this article, you saw how easily we can extend the sample application and add new features to the application by using the Azure SDK and Azure Mobile Services. In the next article, we’ll discuss how to add offline sync capabilities to the application.