diff --git a/Doc/Img/2017-12-25_11-28-43.png b/Doc/Img/2017-12-25_11-28-43.png new file mode 100644 index 0000000..27b1c27 Binary files /dev/null and b/Doc/Img/2017-12-25_11-28-43.png differ diff --git a/Doc/Img/2017-12-25_11-29-38.png b/Doc/Img/2017-12-25_11-29-38.png new file mode 100644 index 0000000..47b173f Binary files /dev/null and b/Doc/Img/2017-12-25_11-29-38.png differ diff --git a/Doc/Img/2017-12-25_11-31-10.png b/Doc/Img/2017-12-25_11-31-10.png new file mode 100644 index 0000000..d9dea63 Binary files /dev/null and b/Doc/Img/2017-12-25_11-31-10.png differ diff --git a/Doc/Img/2017-12-25_11-31-59.png b/Doc/Img/2017-12-25_11-31-59.png new file mode 100644 index 0000000..8bb9804 Binary files /dev/null and b/Doc/Img/2017-12-25_11-31-59.png differ diff --git a/Doc/Img/2017-12-25_11-33-09.png b/Doc/Img/2017-12-25_11-33-09.png new file mode 100644 index 0000000..627ae9e Binary files /dev/null and b/Doc/Img/2017-12-25_11-33-09.png differ diff --git a/Doc/Img/2017-12-25_11-33-36.png b/Doc/Img/2017-12-25_11-33-36.png new file mode 100644 index 0000000..1c7df7a Binary files /dev/null and b/Doc/Img/2017-12-25_11-33-36.png differ diff --git a/Doc/Img/2017-12-25_11-40-33.png b/Doc/Img/2017-12-25_11-40-33.png new file mode 100644 index 0000000..272ef9a Binary files /dev/null and b/Doc/Img/2017-12-25_11-40-33.png differ diff --git a/Doc/Img/2017-12-25_11-41-25.png b/Doc/Img/2017-12-25_11-41-25.png new file mode 100644 index 0000000..700867c Binary files /dev/null and b/Doc/Img/2017-12-25_11-41-25.png differ diff --git a/Doc/Img/2017-12-25_12-14-21.png b/Doc/Img/2017-12-25_12-14-21.png new file mode 100644 index 0000000..b1fd793 Binary files /dev/null and b/Doc/Img/2017-12-25_12-14-21.png differ diff --git a/Doc/Img/2017-12-25_12-15-02.png b/Doc/Img/2017-12-25_12-15-02.png new file mode 100644 index 0000000..77499ea Binary files /dev/null and b/Doc/Img/2017-12-25_12-15-02.png differ diff --git a/Doc/Img/2017-12-25_12-22-15.png b/Doc/Img/2017-12-25_12-22-15.png new file mode 100644 index 0000000..0cc3cef Binary files /dev/null and b/Doc/Img/2017-12-25_12-22-15.png differ diff --git a/Doc/Img/2017-12-25_12-23-13.png b/Doc/Img/2017-12-25_12-23-13.png new file mode 100644 index 0000000..a74a8ba Binary files /dev/null and b/Doc/Img/2017-12-25_12-23-13.png differ diff --git a/Doc/Img/2017-12-25_12-24-48.png b/Doc/Img/2017-12-25_12-24-48.png new file mode 100644 index 0000000..986b787 Binary files /dev/null and b/Doc/Img/2017-12-25_12-24-48.png differ diff --git a/Doc/Img/2017-12-25_12-25-55.png b/Doc/Img/2017-12-25_12-25-55.png new file mode 100644 index 0000000..2b59325 Binary files /dev/null and b/Doc/Img/2017-12-25_12-25-55.png differ diff --git a/Doc/Img/2017-12-25_12-51-53.png b/Doc/Img/2017-12-25_12-51-53.png new file mode 100644 index 0000000..ddc3274 Binary files /dev/null and b/Doc/Img/2017-12-25_12-51-53.png differ diff --git a/Doc/Img/2017-12-25_12-55-16.png b/Doc/Img/2017-12-25_12-55-16.png new file mode 100644 index 0000000..117b622 Binary files /dev/null and b/Doc/Img/2017-12-25_12-55-16.png differ diff --git a/Doc/Img/2017-12-27_14-26-46.png b/Doc/Img/2017-12-27_14-26-46.png new file mode 100644 index 0000000..05e17b9 Binary files /dev/null and b/Doc/Img/2017-12-27_14-26-46.png differ diff --git a/Doc/Img/2018-01-03_14-40-53.png b/Doc/Img/2018-01-03_14-40-53.png new file mode 100644 index 0000000..26118a3 Binary files /dev/null and b/Doc/Img/2018-01-03_14-40-53.png differ diff --git a/Doc/Img/2018-01-04_11-14-39.png b/Doc/Img/2018-01-04_11-14-39.png new file mode 100644 index 0000000..6418c51 Binary files /dev/null and b/Doc/Img/2018-01-04_11-14-39.png differ diff --git a/Doc/Img/2018-01-04_11-15-00.png b/Doc/Img/2018-01-04_11-15-00.png new file mode 100644 index 0000000..83874ee Binary files /dev/null and b/Doc/Img/2018-01-04_11-15-00.png differ diff --git a/Doc/Img/2018-01-04_11-30-09.png b/Doc/Img/2018-01-04_11-30-09.png new file mode 100644 index 0000000..d0cdc5d Binary files /dev/null and b/Doc/Img/2018-01-04_11-30-09.png differ diff --git a/Doc/Img/2018-01-04_11-32-51.png b/Doc/Img/2018-01-04_11-32-51.png new file mode 100644 index 0000000..35fb2c6 Binary files /dev/null and b/Doc/Img/2018-01-04_11-32-51.png differ diff --git a/Doc/Img/2018-01-04_11-34-15.png b/Doc/Img/2018-01-04_11-34-15.png new file mode 100644 index 0000000..78f65a8 Binary files /dev/null and b/Doc/Img/2018-01-04_11-34-15.png differ diff --git a/Doc/Img/2018-01-04_11-34-46.png b/Doc/Img/2018-01-04_11-34-46.png new file mode 100644 index 0000000..fb6605c Binary files /dev/null and b/Doc/Img/2018-01-04_11-34-46.png differ diff --git a/Doc/Img/2018-01-04_11-35-04.png b/Doc/Img/2018-01-04_11-35-04.png new file mode 100644 index 0000000..2346bac Binary files /dev/null and b/Doc/Img/2018-01-04_11-35-04.png differ diff --git a/Doc/Img/2018-01-04_11-35-45.png b/Doc/Img/2018-01-04_11-35-45.png new file mode 100644 index 0000000..d395a69 Binary files /dev/null and b/Doc/Img/2018-01-04_11-35-45.png differ diff --git a/Doc/Img/2018-01-04_15-18-41.png b/Doc/Img/2018-01-04_15-18-41.png new file mode 100644 index 0000000..fbb5b2b Binary files /dev/null and b/Doc/Img/2018-01-04_15-18-41.png differ diff --git a/Doc/Img/2018-01-04_15-19-44.png b/Doc/Img/2018-01-04_15-19-44.png new file mode 100644 index 0000000..b4dd713 Binary files /dev/null and b/Doc/Img/2018-01-04_15-19-44.png differ diff --git a/Doc/Img/2018-01-04_15-24-40.png b/Doc/Img/2018-01-04_15-24-40.png new file mode 100644 index 0000000..3e0a986 Binary files /dev/null and b/Doc/Img/2018-01-04_15-24-40.png differ diff --git a/Doc/Img/2018-01-04_15-25-17.png b/Doc/Img/2018-01-04_15-25-17.png new file mode 100644 index 0000000..165826d Binary files /dev/null and b/Doc/Img/2018-01-04_15-25-17.png differ diff --git a/Doc/Img/2018-01-04_15-26-08.png b/Doc/Img/2018-01-04_15-26-08.png new file mode 100644 index 0000000..1f43e90 Binary files /dev/null and b/Doc/Img/2018-01-04_15-26-08.png differ diff --git a/Doc/Img/2018-01-04_15-30-54.png b/Doc/Img/2018-01-04_15-30-54.png new file mode 100644 index 0000000..69e6ef3 Binary files /dev/null and b/Doc/Img/2018-01-04_15-30-54.png differ diff --git a/Doc/Img/2018-01-04_20-33-16.png b/Doc/Img/2018-01-04_20-33-16.png new file mode 100644 index 0000000..4f06ad4 Binary files /dev/null and b/Doc/Img/2018-01-04_20-33-16.png differ diff --git a/Doc/Img/2018-01-04_20-33-37.png b/Doc/Img/2018-01-04_20-33-37.png new file mode 100644 index 0000000..4de64c4 Binary files /dev/null and b/Doc/Img/2018-01-04_20-33-37.png differ diff --git a/Doc/Img/2018-01-04_20-35-52.png b/Doc/Img/2018-01-04_20-35-52.png new file mode 100644 index 0000000..ebff75b Binary files /dev/null and b/Doc/Img/2018-01-04_20-35-52.png differ diff --git a/Doc/Img/2018-01-05_13-43-24.png b/Doc/Img/2018-01-05_13-43-24.png new file mode 100644 index 0000000..4b81e4b Binary files /dev/null and b/Doc/Img/2018-01-05_13-43-24.png differ diff --git a/Doc/Img/2018-01-08_09-53-48.png b/Doc/Img/2018-01-08_09-53-48.png new file mode 100644 index 0000000..d6dfb9c Binary files /dev/null and b/Doc/Img/2018-01-08_09-53-48.png differ diff --git a/Doc/Img/2018-01-08_16-12-08.png b/Doc/Img/2018-01-08_16-12-08.png new file mode 100644 index 0000000..676ee24 Binary files /dev/null and b/Doc/Img/2018-01-08_16-12-08.png differ diff --git a/Doc/Img/2018-01-08_17-23-14.png b/Doc/Img/2018-01-08_17-23-14.png new file mode 100644 index 0000000..f56b2a5 Binary files /dev/null and b/Doc/Img/2018-01-08_17-23-14.png differ diff --git a/Doc/Img/2018-01-08_17-43-56.png b/Doc/Img/2018-01-08_17-43-56.png new file mode 100644 index 0000000..3c79e96 Binary files /dev/null and b/Doc/Img/2018-01-08_17-43-56.png differ diff --git a/Doc/Img/2018-01-08_17-45-48.png b/Doc/Img/2018-01-08_17-45-48.png new file mode 100644 index 0000000..df2aa41 Binary files /dev/null and b/Doc/Img/2018-01-08_17-45-48.png differ diff --git a/Doc/Img/2018-01-08_18-06-01.png b/Doc/Img/2018-01-08_18-06-01.png new file mode 100644 index 0000000..514fb0c Binary files /dev/null and b/Doc/Img/2018-01-08_18-06-01.png differ diff --git a/Doc/Img/2018-01-14_10-57-00.png b/Doc/Img/2018-01-14_10-57-00.png new file mode 100644 index 0000000..1227149 Binary files /dev/null and b/Doc/Img/2018-01-14_10-57-00.png differ diff --git a/Doc/Img/2018-01-15_15-01-00.png b/Doc/Img/2018-01-15_15-01-00.png new file mode 100644 index 0000000..0d59626 Binary files /dev/null and b/Doc/Img/2018-01-15_15-01-00.png differ diff --git a/Doc/Img/2018-01-15_15-57-00.png b/Doc/Img/2018-01-15_15-57-00.png new file mode 100644 index 0000000..3ffde37 Binary files /dev/null and b/Doc/Img/2018-01-15_15-57-00.png differ diff --git a/Doc/Img/2018-01-15_16-15-00.png b/Doc/Img/2018-01-15_16-15-00.png new file mode 100644 index 0000000..4e9c054 Binary files /dev/null and b/Doc/Img/2018-01-15_16-15-00.png differ diff --git a/Doc/Img/Azure-Functions-Logo.png b/Doc/Img/Azure-Functions-Logo.png new file mode 100644 index 0000000..c9488e0 Binary files /dev/null and b/Doc/Img/Azure-Functions-Logo.png differ diff --git a/Doc/creating-vs.md b/Doc/creating-vs.md new file mode 100644 index 0000000..9ee988c --- /dev/null +++ b/Doc/creating-vs.md @@ -0,0 +1,146 @@ +# Creating the Azure Function in Visual Studio + +The great thing with the Azure tooling is that you can decide what tools you are more comfortable with. You can decide to [create the function in the Azure web portal](./creating.md), or you can take advantage of Visual Studio and its complete suite of tools, including unit testing, performance analysis, local debugging etc. In this section, we will show how the function can be created in Visual Studio, how to run the function locally to test it and how to publish it to Azure. + +> Note: You can find more tutorials and quickstarts on the Azure Functions documentation page](http://gslb.ch/a10). + +## Creating the function application + +To create the function application in Visual Studio, you will need Visual Studio 2017. You can perform these steps in any edition of Visual Studio, [including the free Community edition](http://gslb.ch/a72). In the installer, make sure that the Azure development workload is installed. + +![Visual Studio installer](./Img/2018-01-05_13-43-24.png) + +1. Start Visual Studio 2017. + +2. Select File > New > Project from the menu bar. + +3. In the New Project dialog, select the Cloud category and then Azure Functions. + +4. Enter a name for the Function application. Note that you can have multiple functions in one Function application. Then press OK. + +5. In the New Template dialog, select Http trigger and the following options: + + - Azure Functions v2 Preview (.NET Core). If you prefer, you can also select Azure Functions v1 (.NET Framework). The advantage of a .NET core function application is that it can run on servers with Linux. However some features are unavailable at this point. + - Under Storage Account, select None. This particular sample doesn't require storage. However if your function needs data, tables, etc., you may want to connect it to an Azure Storage account. + - Set Access rights to Function. + +![New Template dialog](./Img/2018-01-15_15-01-00.png) + +When the function application is created, it gives the default name "Function1" to the function. You will need to rename it to something more meaningful. + +5. Rename the ```Function1.cs``` file to ```Add.cs```. + +6. Open the ```Add.cs``` file in the code editor and modify the code as shown here: + +```CS +public static class Add +{ + [FunctionName("Add")] + public static IActionResult Run( + [HttpTrigger( + AuthorizationLevel.Function, + "get", + Route = "add/num1/{num1}/num2/{num2}")] + HttpRequest req, + int num1, + int num2, + TraceWriter log) + { + log.Info($"C# HTTP trigger function processed a request with {num1} and {num2}"); + + var addition = num1 + num2; + + return new OkObjectResult(addition); + } +} +``` + +There are a few interesting things about the code above: + +- We changed the ```Run``` method's signature. The Azure Functions runtime will use this information to configure the service. First, we removed the ```"post"``` method because we want this function to only accept ```get``` methods. Then we modified the ```Route``` parameter of the ```HttpTrigger``` attribute. We declare the new route to be ```"add/num1/{num1}/num2/{num2}"```. In the client code, when we call the URL, we will replace ```{num1}``` with the first operand of the addition, and ```{num2}``` with the second operand. + +- We declare two parameters named ```num1``` and ```num2``` of type ```int```. Conveniently, the Azure Functions runtime will automatically convert the ```{num1}``` and ```{num2}``` parts of the URL into the corresponding integers. + +- We log an entry when the function is called. You can see the log entry in the debug window later, or in the Azure web portal. Logging can be very useful to debug some difficult issues. + +- We then execute the addition with the two operands and return an ```OkObjectResult``` which will translate to an OK HTTP response . + +> Note: since HTTP is a text-based protocol, the result of the addition will be returned to the client as text. [Later we will see how modern APIs use the JavaScript Object Notation (JSON)](./refactoring.md) to encode API inputs and outputs. JSON can easily be serialized and deserialized. + +## Testing the function + +One of the greatest advantages of Visual Studio over the Azure web portal for function creation and implementation is that you can run the function locally, which is very convenient for test purposes. + +1. In the code editor, in Add.cs, place a breakpoint on the first line of the Run method, where the log call is placed. + +2. Run the function in debug mode. This will start the Azure Functions runtime in a command window. + +> Note: The Azure Functions runtime which is installed locally is an exact copy of the Azure Functions runtime running in Azure. This is not a simulator. This ensures that you get conditions as closed to reality as possible. + +3. At the bottom of the command window, you will find the local URL of the function. Copy this URL which should be similar to ```http://localhost:7071/api/add/num1/{num1}/num2/{num2}``` + +![Command window with Function runtime](./Img/2018-01-15_15-57-00.png) + +4. Open a web browser window and paste the URL in the location bar. + +5. In the URL, replace ```{num1}``` with an integer, for example 12. Then replace ```{num2}``` with another integer, for example 34. Then press Enter to load the page. + +6. The application should break in the debugger in Visual Studio, at the breakpoint that you placed earlier. You can now inspect the ```num1``` and ```num2``` operands, and step through the function's code to debug it. Finally you should see the result, for example ```46``` in the web browser window. + +## Publishing the function to Azure + +Now that we have created and tested the function, we can publish it to Azure. In practice for larger applications, the Publishing step would be taken care of by a script and some tooling. Also, we wouldn't publish to a production server first, but we would deploy to a test server and run additional tests before moving the code to production. + +In this simple sample, we will use the [Publish feature of Visual Studio](http://gslb.ch/a76) instead. + +1. In the Solution Explorer, right click on the functions application and select Publish from the context menu. + +![Publish](./Img/2018-01-04_11-14-39.png) + +2. In the next dialog, select Create New in order to create a new Functions application. In this dialog, you could also select an existing Functions application if you have one that you wish to replace. + +![Publish dialog](./Img/2018-01-04_11-15-00.png) + +3. In the Create Service dialog, set the following information: + +- App Name: This is the name that will be used in the Azure portal. + +> Note: The function's name should be unique and will appear in the function's URL. For example if the function is named LbCalculator, the domain will be ```https://lbcalculator.azurewebsites.net```. + +- Subscription: This is the Azure subscription that will be billed. Note that you can create a free subscription for trial at [https://azure.microsoft.com/free](http://gslb.ch/a17). + +- Resource group: This is a logical grouping of your application's resources, to make it easier to manage them. You can create a new resource group or select am existing one. + +- App service plan: This is the billing plan that you can use for this Azure Functions application. App Service plans can also be used for other app services such as web applications, web APIs, etc. You can find more information about [App service plans in the Azure documentation](https://docs.microsoft.com/en-us/azure/app-service/azure-web-sites-web-hosting-plans-in-depth-overview). + +![Create App Service](./Img/2018-01-04_11-30-09.png) + +3. Click on the Create button. After the publication succeeds you will see a new dialog with information about the application. + +![Successful publication](./Img/2018-01-04_11-32-51.png) + +## Getting the URL for the Xamarin client app + +Later in the sample, we will need the URL of the service for our client app. Since all the communication between the client and the server happens over HTTP, the URL is the interface for it. + +1. Log into the Azure web portal. In the menu on the left, select Function Apps. + +![Azure Web Portal menu](./Img/2018-01-04_11-34-15.png) + +2. Locate the functions application that you just published and click on the Add menu item. + +![Add function](./Img/2018-01-04_11-34-46.png) + +3. Above the code editor window, click on the "Get function URL" button. + +![Get Function URL](./Img/2018-01-04_11-35-04.png) + +4. Copy the URL from the pop-up window and keep it safe for later. + +![Function URL](./Img/2018-01-04_11-35-45.png) + +## Conclusion + +Our function's code is now complete and available for additional features in Visual Studio. We can now [modify to the client app's implementation to use the function](./second-client.md). + +Later we will also refactor [the server](./refactoring.md) and [the client](./refactoring-client.md) to use JavaScript Object Notation JSON to communicate. \ No newline at end of file diff --git a/Doc/creating.md b/Doc/creating.md new file mode 100644 index 0000000..3754ecd --- /dev/null +++ b/Doc/creating.md @@ -0,0 +1,94 @@ +# Creating the Azure Function in the Azure Web Portal + +In this section, we will build the Azure Functions application in the Azure web portal and then add an HTTP Triggered function. This will allow us to call the function from the Xamarin client, for example with an [HttpClient](http://gslb.ch/a75) instance. + +> Note: If you prefer, you can create the Azure Function in Visual Studio 2017 instead. [A detailed tutorial can be found here](./creating-vs.md). + +To create the Azure Functions application in the Azure portal, follow these steps: + +1. Log into the [Azure Portal](http://portal.azure.com) with your user account. + +> Note: You will need an Azure account to create this sample. If you don't have one already, [you can get a free trial account here](http://gslb.ch/a17). + +2. Click the "Create a resource" menu item. + +![Create a resource](./Img/2017-12-25_11-28-43.png) + +3. In the Azure Marketplace, select "Serverless Function App". + +![Serverless Function App](./Img/2017-12-25_11-29-38.png) + +4. Fill the form with the following data: + + - App Name: This is a unique name for your application. One application can contain multiple functions. + + - Subscription: The subscription to which these functions will be billed. In some cases you will only see one subscription here, but some people have multiple subscriptions associated to their account. + + - Resource group: This is a logical grouping of Azure resources. It makes sense to have one resource group per application, so you can easily locate the resources that you are using. In this case we are creating a new resource group for this application. + + - OS: The operating system of the server on which the functions will run. + + - Hosting plan: This shows how the function usage will be billed. + - Consumption plan means that the function will be billed whenever it is called, and only for the time that it runs. This is the best plan to get started. + - App Service Plan is best after your business starts attracting more users and you need some more predictable billing. + + - Location will be the physical location of the server on which your functions will run. You should choose a server close to your users. + + - Storage: You can either create a new storage account, or use an existing one. Note that this sample doesn't use storage but you still need to specify a storage account. + + > Note: The storage account name should be entered in lower case. + + - Application Insights: If you want to add extra analytics on your functions application, you can switch this on. This provides you with stats about the usage, crash reports, custom events, etc. In this sample we will not use Application Insights. + +![Creating the function app](./Img/2017-12-25_11-31-10.png) + +5. Click the Create button. This will trigger the deployment, and you should see a popup like shown below. + +![Deployment in progress](./Img/2017-12-25_11-31-59.png) + +6. After a moment, you should see a new notification: Deployment succeeded. You can then click the button to go to the resource, or simply close the notification. + +![Deployment succeeded](./Img/2017-12-25_11-33-09.png) + +> Note: You can always go back to the application by clicking on the Function Apps menu item on the left-hand side. + +![Function Apps menu item](./Img/2017-12-25_11-33-36.png) + +7. Once you are in the Functions Apps section in the portal, expand the application itself. Next to the "Functions" submenu, click on the "+" sign when you hover over the submenu. + +![Application submenus](./Img/2017-12-25_11-40-33.png) + +Now we need to choose what will *trigger* the function that we will create. There are a large number of triggers available and we cannot review all of them here, but there is [documentation available on our Docs website](http://gslb.ch/a63). The most common triggers are: + +- [HTTP Trigger](http://gslb.ch/a65): The function will be executed when an HTTP request arrives. This is the type of trigger we will use. +- [Timer trigger](http://gslb.ch/a66): The function is executed every interval of time, where the interval is specified [by a CRON expression](https://en.wikipedia.org/wiki/Cron#CRON_expression). +- [Blob trigger](http://gslb.ch/a64): The function is executed when a file is uploaded to a given blob container +- [and more...](http://gslb.ch/a63) + +8. Click on the "Custom function" button as shown below. + +![Custom function](./Img/2017-12-25_11-41-25.png) + +9. You will now see a large list of potential triggers, which can be implemented in various languages. Scroll down until you see the "HTTP trigger with parameter". In this sample, we will create the function in C#, so click the corresponding button. + +![HTTP trigger with parameter](./Img/2017-12-25_12-14-21.png) + +10. Enter a name for the function (for example "Add") and press Create. + +![Function creation](./Img/2017-12-25_12-15-02.png) + +11. The function is created, and some basic implementation is added. Let's test to see how the function works. Since it is an HTTP trigger, we can execute the function by calling a URL. You can get the URL from the top right corner, where the "Get function URL" button is found. + +![Get function URL](./Img/2017-12-25_12-22-15.png) + +12. Copy the URL from the popup window. + +![Function URL](./Img/2017-12-25_12-23-13.png) + +13. Open a web browser window and paste the link into the location bar. Before you press the Enter key, make sure to replace the ```{name}``` parameter in the URL with your own name. Then press enter and you should see the response "Hello Laurent" appear (except that your own name should be shown instead of Laurent). + +## Conclusion + +We now have the infrastructure in place for our Azure Function. Once you are a bit more experienced, the process of creating such a function should not take more than a few minutes. + +[In the next section, we will now modify the function's interface and then implement it.](./implementing.md) \ No newline at end of file diff --git a/Doc/first-client.md b/Doc/first-client.md new file mode 100644 index 0000000..588a764 --- /dev/null +++ b/Doc/first-client.md @@ -0,0 +1,162 @@ +# Implementing the first version of the Xamarin.Forms client app + +We will start this sample by creating a Xamarin.Forms client app which works offline. Then we will see how we can transfer the business logic of this app to the Azure cloud. + +> Note: If you are already familiar with Xamarin.Forms, you can jump to the next step without fear. You will find the client that we create in this page in [the XamCalculator - Start folder](https://github.com/lbugnion/sample-azure-simplexamarinfunction/tree/master/XamCalculator%20-%20Start). + +The Xamarin client app that we create here is extremely simple and obviously not a real life scenario. However it shows all the steps necessary to creating the client and the server applications, and it should give you a good jumpstart into your own projects and use cases. + +1. In Visual Studio 2017, select File > New > Project. + +> Note: We use Visual Studio 2017 on Windows for this sample, but you can also create Xamarin.Forms applications in Visual Studio for Mac if you prefer. Xamarin is available for free in all editions of Visual Studio, including the free Community edition, on PC and Mac. +> - [Visual Studio Community Edition for Windows](http://gslb.ch/a72) +> - [Visual Studio for Mac](http://gslb.ch/a73) + +2. In the New Project dialog, select the Cross-Platform category, and then Cross-Platform App (Xamarin.Forms) with Visual C#. Name the new application ```XamCalculator```, select a location for the project and press OK. + +![New Project](./Img/2017-12-25_12-51-53.png) + +> Note: The Cross-platform category is available if you selected the "Mobile development with .NET" workload in the Visual Studio 2017 installer. + +3. In the New Cross Platform App dialog, select the following settings, then press OK. + - Android, iOS and Windows + - Xamarin.Forms + - .NET Standard + +![New Cross Platform App](./Img/2017-12-25_12-55-16.png) + +The new application consists of 4 projects: + +- XamCalculator: This is the shared .NET Standard project, where we will implement the UI and the code calling the function. This project is referenced by each of the 3 other projects. +- XamCalculator.Android: The Android version of the application. +- XamCalculator.iOS: The iOS version of the application. +- XamCalculator.UWP: The Universal Windows Platform (UWP) of the application. + +Later we will see how we can select each application to test it and run it. + +4. In the XamCalculator project, select the MainPage.xaml and open it in the editor. + +5. Replace the existing XAML with the following: + +```xml + + + + + + + + + +