RUNNING .NET APPLICATIONS ON A RASPBERRY PI THAT COMMUNICATES WITH AZURE
- This post exists to help with an MSDN Magazine article that I am authoring
- It provides some of the low-level details for the article
- How to install Mono and root certificates on a raspberry pi
- How to create an Azure mobile service
- How to create a Custom API inside Azure mobile services that the raspberry pi can call into
- How to create an Azure storage account
RELATED ARTICLES
MONO - HOW TO INSTALL ON A RASPBERRY PI
- Why Mono?
- How to install Mono on a raspberry pi
- Installing trusted root certificates on to the raspberry pi
- https://www.mono-project.com/Main_Page
- An open source, cross-platform, implementation of C# and the CLR that is binary compatible with Microsoft.NET
- Mono is a free and open source project led by Xamarin (formerly by Novell) that provides a .NET Framework-compatible set of tools including, among others, a C# compiler and a Common Language Runtime
WHY MONO?
- Because it lets us write .net code compiled on Windows
- We can simply copy the binary files from Windows to Linux and run it as is
- From a raspberry pi device, it is possible to use a .net application to take a photo and upload it to Windows Azure storage
HOW TO INSTALL ON A RASPBERRY PI RUNNING LINUX
You will issue the following commands:
pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get install mono-complete
The first command makes sure all the local package index are up to date with the changes made in repositories. Second command installs the complete Mono tooling and runtime.
MAKING SURE THAT YOUR MONO APPLICATIONS CAN MAKE A HTTPS REST-BASED CALLS
This command downloads the trusted root certificates from the Mozilla LXR web site into the Mono certificate store. Once complete, the Raspberry PI will be capable of making web requests using HTTPS requests within Mono.
pi@raspberrypi ~ $ mozroots --import --ask-remove --machine
CREATING A NEW AZURE MOBILE SERVICES ACCOUNT
- The mobile services account is needed to host a Node.js application that provides shared access signatures to raspberry pi devices
- The shared access signature is needed by the raspberry pi, so that it can directly and securely upload photos to Azure storage
STEPS TO CREATE AN AZURE MOBILE SERVICE
- The steps below will create an Azure mobile service
- The service will be used to host a Node.js application interacting with a raspberry pi devices
- We will provision a SQL database, although it will not be used initially
FOLLOW THESE STEPS TO CREATE THE MOBILE SERVICE
- Login into the Azure Portal
- Select MOBILE SERVICES from the left menu pane at the Azure Portal.
- In the lower left corner select "+NEW" to create a new Azure Mobile Service.
- Make sure you've selected, "COMPUTE / MOBILE SERVICE / CREATE."
- You will now enter a url. We will call this service raspberrymobileservice.
- For the DATABASE, we will choose "Create a new SQL database instance."
- The REGION we chose is "West US."
- The BACKEND is "JavaScript."
- Click the "->" arrow to proceed to the next screen.
- In this screen you will "Specify database settings."
- The NAME of your database will based on the URL you entered previously.
- In this case, the database is called "raspberrymobileservice_db."
- You will need to choose a SERVER. We will choose "New SQL database server" from the drop-down list.
- You will need to provide a SERVER LOGIN NAME and a SERVER LOGIN PASSWORD.
- Take note of the login you provided as it will be needed later
CREATING A CUSTOM API
- Azure mobile services allows you to create a custom API written in JavaScript that can be called from a raspberry pi device using REST
- This custom API is really just a Node.js application running in the server
CREATING THE API TO RESPOND TO THE DEVICE TRYING TO UPLOAD PHOTOS
Now that the service is established, we will turn our attention to creating an API that the device can call into to upload a photo.
Login into the Azure Portal
Your mobile service will take a few minutes to complete, and you should see the "Ready" flag as the "Status" for your service.
Once it is ready you can drill into your service to customize its behavior. Just to the right of the service name, click the right arrow key "->" to drill into the service details.
- The top menu bar will offer many options, but we are interested in the one titled "API."
- The API allows you to create a series of node.JS API calls that a device can call into using rest-based approaches.
Click on "API." from there, select "CREATE A CUSTOM API." You will be asked to provide an API name. Type in "photos" for the API name.
Below you will see a series of drop-down combo boxes that relate to permission.
We will keep the default value of "Anybody with the application key."
- This might not be the best option for all scenarios.
- You can read more about this here. https://msdn.microsoft.com/en-us/library/azure/jj193161.aspx.
Click the checkmark to complete the process.
The name of the AP you just created, "Photos," should be visible on the portal interface.
To drill into the photos API click on the right arrow key "->". The right arrow key will be just to the right of the name of the API "Photos".
At this point you should see a basic script that has been provided by default. We will overwrite this default script with our own script as described in the MSDN Magazine article.
CREATING A STORAGE ACCOUNT TO STORE THE PHOTOS
- Navigate to the portal and create a storage account
- Create a container for the photos
- Obtain the:
- Storage Account Name (you will provide a name)
- Storage Account Access key (generated for you)
- Container Name (you will create)
CREATING A STORAGE ACCOUNT
We will need a storage account so that we can upload photos to it.
The steps are well documented here: https://azure.microsoft.com/en-us/documentation/articles/storage-create-storage-account/
In our case we call the storage account raspberrystorage.
- This means that the URL that the device will use to upload photos is https://raspberrystorage.blob.core.windows.net/.
As you complete these steps make sure that you choose the storage account location to be the same location as was used for your mobile services account.
This avoids any unnecessary latency or bandwidth costs between data centers.
Once the storage account is created, we will need to create a container within it.
Photos or any blob for that matter, are always stored within a container. To create a container drill into your newly created storage account and select CONTAINERS from the top menu. From there, select CREATE A CONTAINER. The new container dialog box will ask for a name for your container. Take note of the name you provide. We are calling our container ?photocontainer.?
- When the raspberry pi device uploads photos to the storage account, it will target a specific container, such as the one we just created. You will next be asked to indicate ACCESS rights. To keep things simple we will select access rights of Public Blob.
ENTERING APP SETTINGS
- Rather than hard-code storage account information inside your JavaScript/Node.js applications, you should consider using apps settings inside of the Azure mobile services portal
- This post also discusses it well:
-
- ?The idea of application settings is a set of key-value pairs which can be set for the mobile service (either via the portal or via the command-line interface), and those values could be then read in the service runtime.?
-
NAVIGATING TO APP SETTINGS
- Navigate to the Azure Mobile Services section of the portal. Drill into the specific service by hitting the arrow below
- Select from the Configure Menu at the top
- Scroll down to the very bottom to see app settings
- Note that we need to enter: - We need to get this from Azure Storage - PhotoContainerName - AccountName - AccountKey
- We get this information from the Azure Storage Section of the Portal. Note that you need to have provisioned a Storage Account to have this information.
- How to get the AccountKey with Azure Storage Services
- Now you can get the access keys
HOW NODE.JS WILL ACCESS THE APP SETTINGS
You will create a Node.js application inside of Azure Mobile Services
- See previous steps
THE NODE.JS APPLICATION READING APP SETTINGS
- You will starting by going back to Azure Mobile Services and drill down into your newly minted service
- We called ours raspberrymobileservice
Once you click API, you should see:
Notice the app settings are being read on lines 12 to 14.## Comments
Anonymous
June 12, 2014
It seems strange to me to go to the trouble of installing Mono on the Rasberry Pi so you can use .NET on it, and then use Node.js on Azure on the backend. Seems like the purpose of using Mono on the client is so that you can have an end to end solution that only uses .NET. What is the preference? Python, C/C++? What architecture do you propose to run JavaScript on the client? ~BrunoAnonymous
June 13, 2014
Seems to me for a microsoft blog weird to get updating on a linux device wrong. Surely apt-get upgrade would be actually making sure the Pi is up to date. apt-get update just refreshes repo lists? You would think that updating would be the one thing microsoft users would get right by now....Anonymous
June 13, 2014
Ryan W - he has the commands correct. He is refreshing the repo lists and then installing mono. He's not upgrading the device to the latest versions so there is no need for apt-get upgrade.Anonymous
June 20, 2014
I don't see a way to respond directly to these questions: "What is the preference? Python, C/C++? What architecture do you propose to run JavaScript on the client?" I was thinking C# for everything. Maybe I'm misunderstanding things. In reference to this statement: "You will create a Node.js application inside of Azure Mobile Services" This gave me the impression that the backend of the mobile service will be using JavaScript code and running under the Node.js interpreter. The example JavaScript code you are including to access configuration settings seems like it will be running on the server side as part of an Azure Mobile Service. This seemed awkward to me to install Mono on the client so you can code in .NET supported languages, but then select Node.js on the server and be forced to code in JavaScript. I checked my own Azure account for creating a mobile service, and "JavaScript" is currently the only non-preview option for the backend for a mobile service. .NET is currently available as a "preview" option. It's strange to me that Microsoft would have Javascipt as a mobile service backend before .NET, but that's probably the answer to my question. JavaScript is the currently the only "supported" backend for an Azure Mobile Service. Now that I've tried my best to clarify my first post, do you still have the same questions?Anonymous
June 20, 2014
Your impression was right. But at the end of the day my code is JavaScript running on the server. Specifically, it is Node.js. The language is Javascript. All the node.js packages are supported. It is a great implementation of Node.js. The only difference is that it is running within Azure Mobile Services. Your statement is not true that " 'JavaScript' is currently the only non-preview option for the backend for a mobile service." There are many, many options in Azure to supporting mobile services. You could base your "mobile service" in a variety of languages and cloud-based options, such as Azure Web Sites, Virtual Machine of your choice (Linux, Windows). You could use WCF or RESTful services running ASP.NET Web API in Azure Web Roles or on a VM. You've got Python, Java, PHP, WordPress, Drupal. Yes, I chose Mobile Services because I like the way it supports Node.js programs. I could have hosted Node.js in many more places than just Mobile Servcies. To me it makes no sense to look at Azure Mobile Services alone, as an end in itself - it is merely one of serveral service abstractions that have been engineered to help developers program in their favorite languages, operating systems, and tooling. I don't think this "strange" at all :-) Regarding Mono on the client being in any way incongruent with the backend of JavaScript/Node.js is not the best approach. If you have a lot of devs that know Node.js and have libraries that work, why should they write C# code just to be like the client? In my view, back-end services should be built with the best tool for just the backend, with hardly any concern of the client. I don't believe there is anything in Azure whereby, in your own words, "you are forced to code in Javascript." Now, with that said, Node.js is beautiful because it perfectly embraces Javascript on client too. Node.js packages provide both client and server functionality and parity is awesome, especially if JSON is the data exchange. So if C# is what you want, then I'd take a look at the ASP.NET Web Api. There are some great libraries that can help you get a shared access signature, upload blobs and everything I showed you. ~BrunoAnonymous
June 22, 2014
From what I can tell, "Mobile Services" is a specific product of Microsoft Azure. I was not using it in a generic fashion. There are 2 backend selections currently: JavaScript: www.ucarecdn.com/.../MobileServiceJavascript.png .NET (PREVIEW) www.ucarecdn.com/.../MobileServiceDotNet.png If you choose JavaScript as the backend when the instance of your "Mobile Services" is created, there does not seem to be a way to change that configuration later. You are "forced" to use JavaScript on the backend for that instance. This architecture just seems backwards to me. ASP.NET developers have been using C# (and other .NET languages) on the server for over 10 years and JavaScript on the client. The architecture in your article switches these around. To me, it seems that any solution that only uses one language is better than a solution that uses multiple languages. Needing to manage code in 2 languages is not twice as hard as one language, but it is more difficult. Does Node.js on the Raspberry Pi not have the needed features for your application?Anonymous
June 22, 2014
IMHO, using 2 languages COULD be half as difficult as using one. The extreme example is building device drivers in C versus a thick client app in Java or C#. Building a thick client in C is a lot more work. The libraries and abstractions in C# make thick client development far easier. In the context of Node.js, I think the packages found here, https://www.npmjs.org/, could potentially make your server code much easier for specific use case scenarios, as compared to other languages. You could end up with a much smaller code base because the libraries may solve your particular problem really well. Less code in a 2nd language is better than lots of code in the same language. Language choice often ends in a religious war about which language is better. My response is, "to each their own - choose what you are most productive with." As for me, I'm always open to using a second or third language if it results in smaller, more robust code in a shorter amount of time. Cheers! ~BrunoAnonymous
July 24, 2014
I'm getting this while trying to install the root certificates: Importing certificates into machine store... Error: System.UnauthorizedAccessException: Access to the path "/usr/share/.mono" is denied. at System.IO.Directory.CreateDirectoriesInternal (System.String path) [0x00000] in <filename unknown>:0 at System.IO.Directory.CreateDirectory (System.String path) [0x00000] in <filename unknown>:0 at System.IO.DirectoryInfo.Create () [0x00000] in <filename unknown>:0 at (wrapper remoting-invoke-with-check) System.IO.DirectoryInfo:Create () at System.IO.Directory.CreateDirectoriesInternal (System.String path) [0x00000] in <filename unknown>:0 at System.IO.Directory.CreateDirectory (System.String path) [0x00000] in <filename unknown>:0 at System.IO.DirectoryInfo.Create () [0x00000] in <filename unknown>:0 at (wrapper remoting-invoke-with-check) System.IO.DirectoryInfo:Create () at System.IO.Directory.CreateDirectoriesInternal (System.String path) [0x00000] in <filename unknown>:0 at System.IO.Directory.CreateDirectory (System.String path) [0x00000] in <filename unknown>:0 at Mono.Security.X509.X509Store.CheckStore (System.String path, Boolean throwException) [0x00000] in <filename unknown>:0 BrunoTry using the "sudo" command, which gives you higher privileges.Anonymous
July 25, 2014
Thanks Bruno! That was exactly what I needed! I'm a noob to Linux, so I appreciate the help!Anonymous
September 07, 2014
I'm getting an error running on the Raspberry PI - "System.IO.FileNotFoundException Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0" I've tried installing previous version of Newtonsoft in VS2013. I've got Mono version 3.2.8 on the PiAnonymous
October 20, 2014
So Colin_C You solved the problem?Anonymous
November 03, 2014
The comment has been removedAnonymous
January 07, 2015
The comment has been removed