Udostępnij za pośrednictwem


How to create custom APIs and scheduled jobs in a mobile service (.NET backend)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

A custom API in a mobile service is a function that your client apps can call. See Custom API. When you work with mobile services in Visual Studio, you can add a custom API and edit it in Visual Studio. A custom API is created as an HTTP endpoint in the form of a REST API. Examples of using custom APIs are to return data from a query, and to make updates to a database that require more processing than is possible in a simple update script, or involve more than one data table.

This topic applies to the .NET backend. If you're using the JavaScript backend, see How to create custom APIs in a mobile service (JavaScript backend).

Prerequisites

  • Windows 8.1
  • Microsoft Visual Studio 2013
  • Microsoft Visual Studio 2013 Update 2
  • An Azure subscription. If you don't have an account, you can create a free trial account in just a couple of minutes. For details, see Azure Free Trial.
  • A mobile service .NET backend project in C# or Visual Basic, and a client project to call the API, such as the result of completing this quickstart.

Instructions

Step 1: Add a custom controller

  1. In Solution Explorer, open the shortcut menu and choose Add > New Scaffolded Item.

    Note  A scaffold is a controller class which provides default implementations for operations on your data.

     

  2. In the Add Scaffold dialog box, choose Mobile Services Custom Controller.

  3. In the Add Controller dialog, enter a name for the custom API controller, and choose the Add button. The name should end in Controller.

    A file is added to your project that contains the code for the controller, with a built-in HTTP method.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    using Microsoft.WindowsAzure.Mobile.Service;
    
    namespace TodoListMobileService.Controllers
    {
        public class UndoneCountController : ApiController
        {
               public ApiServices Services { get; set; }
    
                  // GET api/UndoneCount
            public string Get()
            {
                Services.Log.Info("Hello from custom controller!");
                return "Hello";
            }
    
        }
    }
    
    Imports System.Net
    Imports System.Web.Http
    Imports Microsoft.WindowsAzure.Mobile.Service
    
    Public Class UndoneCountController
        Inherits ApiController
    
           Public Property Services As ApiServices
    
           ' GET api/UndoneCount
           Public Function GetValues() As String
                  Services.Log.Info("Hello from custom controller!")
                  Return "Hello"
           End Function
    
    End Class
    

Step 2: Edit the custom API

You can now write code for your custom API. A custom API can include one or more of the HTTP verbs GET, POST, PUT, PATCH, or DELETE.

  1. In the Get method, add the following code:

    using System.Net.Http;
    using System.Web.Http;
    using Microsoft.WindowsAzure.Mobile.Service;
    
    namespace TodoListMobileService.Controllers
    {
        public class UndoneCountController : ApiController
        {
            public ApiServices Services { get; set; }
    
            // GET api/UndoneCount
            public string Get()
            {
                TodoListMobileService.Models.TodoListMobileServiceContext context = new Models.TodoListMobileServiceContext();
                var queryResults = from item in context.TodoItems
                                   where item.Complete == false
                                   select item;
                var count = queryResults.Count();
                Services.Log.Info("Hello from custom controller!");
                return count.ToString();
            }
    
        }
    }
    
    Imports System.Linq
    Imports System.Net
    Imports System.Web.Http
    Imports Microsoft.WindowsAzure.Mobile.Service
    
    Public Class UndoneCountController
        Inherits ApiController
    
        Public Property Services As ApiServices
    
        ' GET api/UndoneCount
        Public Function GetValues() As String
            Dim context As New MobileService2Context
            Dim queryResults = From item In context.TodoItems
                               Where item.Complete = False
                               Select item
            Dim count = queryResults.Count
            Services.Log.Info("Hello from custom controller!")
            Return count.ToString
        End Function
    
    End Class
    
  2. Build the solution.

Step 3: Run the mobile service locally

Entity Framework automatically updates the database schema for the new table, but those changes don't take place until you actually use the table. In this step, you run the mobile service on the local computer and submit a POST to it.

  1. If you have an open connection to the localdb database that your mobile services uses, close it. In Server Explorer, choose the node for the database, choose Close Connection. If you don't do this, the new table won't be created successfully since it requires an exclusive lock on the database.

  2. In Solution Explorer, choose the mobile service project node, open the short cut menu, and choose Set As Startup Project.

  3. Press F5 or choose Start Debugging from the Debug menu. The mobile service starts, and a browser window appears with a test page for your service.

  4. Choose the try it out link.

  5. Locate the name of the new API in the list, and choose the link for the GET method.

  6. Click try this out to run the custom API.

    When the api completes, you see the response.

  7. Close the browser windows.

Step 4: Add client code to call the custom API

  • Insert code in the client app to call the custom API. You use the InvokeApiAsync method to call a mobile service. You need a class to hold the result. For the above example, the following type will suffice.

    public class UndoneCountResult
    {
        public int Count { get; set; }
    }
    

    For the example code above, your client code might look like this in the MainPage class.

    private async void ButtonUndoneCount_Click(object sender, RoutedEventArgs e)
    {
        string message;
        try
        {
            // Asynchronously call the custom API using the GET method. 
            var result = await App.MobileService
                .InvokeApiAsync<UndoneCountResult>("UndoneCount", 
                System.Net.Http.HttpMethod.Get, null);
            message =  result.Count + " item(s) undone.";
            RefreshTodoItems();
        }
        catch (MobileServiceInvalidOperationException ex)
        {
            message = ex.Message;                
        }
    
        var dialog = new MessageDialog(message);
        dialog.Commands.Add(new UICommand("OK"));
        await dialog.ShowAsync();
    }
    

    To complete this example with the sample project, edit MainPage.xaml to add a button that, when clicked, calls the above code.

    <StackPanel Orientation="Horizontal">
        <Button Margin="72,0,0,0" Name="ButtonRefresh" 
                Click="ButtonRefresh_Click">Refresh</Button>
        <Button Margin="12,0,0,0" Name="ButtonCompleteAll" 
                Click="ButtonCompleteAll_Click">Complete All</Button>
    </StackPanel>
    

Step 5: Pass parameters in a custom API

You can pass parameters to a custom API using a dictionary object that contains the parameter names and values as strings. The values must be strings but Web API attempts to convert parameters to appropriate types based on the declaration of the custom API. In this example, you'll add an API that you could use to send a todo list as an email when a user clicks on a button on the client.

  1. Add a new custom controller, called MailController, and add code in the Post method to send an email. You can use either Get or Post, depending on how you want to design your custom APIs. Include a parameter for the recipient's email address. For this example, you can just leave the SendMail method unimplemented, but later you can use the SendGrid email service in Azure to implement this method.

        public void Post(string toAddress)
            {
                Services.Log.Info("MailController Post method called.");
                List<TodoItem> items = context.Database.SqlQuery<TodoItem>("SELECT * FROM TodoItems").ToList();
                string subject = "Your todolist for " + DateTime.Now.ToString();
                string body = "";
                foreach (TodoItem item in items)
                {
                    body = body + item.ToString() + "\n";
                }
                SendMail(toAddress, subject, body);
            }
    
  2. Add client code to call the custom API. You use a Dictionary object to construct the parameters list. The key is the name of the parameter, as a string, and the value is the argument you are providing. Also, add a click event handler for a button you'll add to call this method with an example email address.

    public async void SendMail(string toAddress)
            {
                IDictionary<string, string> parameters = new Dictionary<string, string>();
                parameters.Add("toAddress", toAddress);
                await App.mydotnetbackendtodolist12345Client.InvokeApiAsync("Mail",
                    System.Net.Http.HttpMethod.Post, parameters);
            }
    
            public void ButtonSendMail_Click(object sender, RoutedEventArgs args)
            {
                SendMail("joe@contoso.com");
            }
    
  3. Add a button in XAML to let the user call the new code. Add this code before the last Grid closing tag to locate the button below the other UI elements.

    <StackPanel Orientation="Horizontal">
        <Button Margin="72,0,0,0" Name="ButtonSendMail" Click="ButtonSendMail_Click">Send Mail</Button>
    
    </StackPanel>
    

Step 6: Set permissions on the controller methods

By default, an anonymous Internet user cannot access a mobile service methods unless they have the application key. This procedure shows how to change the authorization. You can use the AuthorizeLevel attribute to enable everyone to access the controller's methods, or to restrict permissions to authenticated users or administrators. See Get started with authentication in Mobile Services. Valid values of the AuthorizationLevel enumeration are Admin (administrators only), Anonymous (no restrictions), Application (requires the application key), and User (requires authenticated credentials).

Warning  Using the Anonymous setting is a potential security risk. You shouldn't grant greater access than your app requires.

 

  1. Open the TodoItemController.cs or .vb file.

  2. Add the following using statement.

    using Microsoft.WindowsAzure.Mobile.Service.Security;
    
    Imports Microsoft.WindowsAzure.Mobile.Service.Security
    
  3. Add the following attribute on the controller class, or in front of each method that you want to set the permissions on.

    [AuthorizeLevel(AuthorizationLevel.Anonymous)]
    
    <AuthorizeLevel(AuthorizationLevel.Anonymous)>
    

Step 7: Add a scheduled job

A scheduled job is a function that runs on the server according to the schedule you specify. It is a way to have code run on the server without being triggered by client apps.

  1. Select the project node for the mobile service project, and choose Add > New Scaffolded Item.

  2. Choose Azure Mobile Services Scheduled Job, and choose the Add button.

  3. In the Add Scheduled Job dialog box, give the job a name, and choose the Add button. It must end with Job.

    Visual Studio adds a code file to your project in a folder called ScheduledJobs.

  4. Implement your job in the ExecuteAsync method. Or, as a test, simply edit the text that gets written to the log in the default implementation.

  5. Open the shortcut menu for the mobile service project, and choose Publish. Unless you want to change any of the settings you chose last time, choose the Publish button.

  6. Choose your service in Server Explorer, open the shortcut menu, and choose Open in Management Portal.

  7. In the management portal, choose your mobile service, and then choose the Scheduler tab.

  8. Choose the link to create a scheduled job.

  9. In the Create a new job dialog box, enter the name of the job that you entered in the Add Scheduled Job dialog box in Step 3, but omit the Job suffix.

  10. Enter how often you want the scheduled job to run and when to start. If you don't want to define the schedule now, set it to On Demand. Choose the checkmark to create the job.

  11. Enable the job by clicking on the Enable button.

  12. Test the job by clicking on the Run Once button.

  13. In Visual Studio, open the shortcut menu for the mobile service node in Server Explorer, and choose View Logs.

Custom API

Call a Custom API from a Windows Store client

Quickstart: Add a mobile service (.NET backend)

How to access data with a custom controller (.NET backend)