Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Hosted-services / Azure

Master the Managed Azure Mobile Services Backend – Part Three

0.00/5 (No votes)
2 Jul 2014CPOL5 min read 8.6K  
Basics of custom controllers

In the second part of this series, you learned about the MVC pattern. ASP.NET, Katana and you created your first managed service using Visual Studio. This part will cover the basics of custom controllers.

Custom Controllers

Custom controllers are usual Web API controllers that you would use in standard Web API and MVC projects. To add a new custom controller to our sample project, “OldSchoolBeats”, right click your “Controllers” folder and choose “Add>Controller…”.

Image 1

The “Add Scaffold” dialog will pop-up. Choose the “Windows Azure Mobile Services Custom Controller” template, and click “Add”. Name the new custom controller “OldSchoolFeedsController”:

Image 2

The new controller will be added to the “Controllers” folder. Like I said before, it is a basic Web API controller, with one difference: There is a public member “Services” of type ApiServices defined. You may wonder what this thing is good for and where it’s actually been set.

Image 3

The ApiServices type can be accessed within your whole managed services project. It is instantiated using dependency injection. The DI-Container used for managed services is Autofac. And because ApiServices is a property, it is done via property-injection. If you want to learn a bit more about Autofac and how the wiring works within the managed backend, I highly recommend this blog-post by Henrik F. Nielsen – he’s a member of the Azure Mobile Services team:

His blog-post provides great resources about Autofac as well. And make sure you stop by on a regular basis – all blog-posts are worth your time.

The ApiServices Class

Like the name states, “ApiServices” has something to do with the core services offered by the managed backend. Here are the “services” that are directly accessible via the ApiServices class.

  • The HttpConfiguration instance
  • The Log instance
  • Access to the push-client
  • Access to the settings dictionary

Without the ApiServices class, it wouldn’t be possible to access the current HttpConfigurationl, to log messages, to send out push-notifications or to access the current settings on the server.

Setting the Access-levels Using the AuthorizationLevelAttribute

Security is very important, not only when you create a new managed service. You should invest a fair amount of time to work-out a basic security strategy. Re-think and re-shape that strategy on a regular base, using all the input-parameters you can get – log-files, firewall-data whatever you can get to make your service more secure and reliable for your users. The standard authorization-level is: Application.

The AuthorizationLevelAttribute gives you a fair amount of options to set the security:

  • for the whole controller
  • or just for a specific controller-action (method)

Four different authorization-levels are available:

  • Anonymous (Anyone can access the controller or action)
  • Application (Only requests that include the application-key can access the controller or action)
  • User (Only requests that include a valid authentication-header can access the controller or action)
  • Admin (Only requests that include the master-key as a header-value can access the controller or action)

Please remember that the AuthorizationAttribute cannot only be used on custom-controllers but on TableControllers and other controller-types as well.

For now, we want to use the AuthorizationLevel.User on our OldSchoolFeedsController. That way, we make sure that only authenticated users can access this controller and its actions (methods).

Returning RSS2.0 from our Database-entries using our Custom Controller

Let’s implement now the GET-Method in our custom controller. Open the file “OldSchoolFeedsController.cs” and implement the GET-Method using the following code. Please notice the new return-type of the method. It’s not “string” anymore, it’s of type “HTTPResponseMessage”:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.ServiceModel.Syndication;
using System.Web.Http;
using System.Web.Http.Description;
using Microsoft.WindowsAzure.Mobile.Service;
using Microsoft.WindowsAzure.Mobile.Service.Security;
using OldSchoolBeats.Models;
using OldSchoolBeats.DataObjects;
using System.Xml;
using System.Text;

namespace OldSchoolBeats.Controllers
{
    [AuthorizeLevel(AuthorizationLevel.User)]
    public class OldSchoolFeedsController : ApiController
    {
        public ApiServices Services { get; set; }

        private ServiceUser currentMobileServicesUser;

        // GET api/OldSchoolFeeds
        /// <summary>
        /// Returns RSS20 compatible feed from our
        /// artist entries in the database.
        /// If there are no entries, only the base
        /// data of the feed will be delivered.
        /// </summary>
        /// <returns></returns>
        public HttpResponseMessage Get()
        {
            if (this.User.Identity.IsAuthenticated)
            {
                this.currentMobileServicesUser = (ServiceUser)this.User;
            }

            //Creating the main-feed thing

            SyndicationFeed feed =
                new SyndicationFeed("Old School Feed", "The coolest old-school rappers.",
                    new Uri("http://www.allmusic.com/subgenre/old-school-rap-ma0000002762/albums"), 
                    "OLDSFEED", DateTime.Now);

            feed.Language = "en-US";            

            List<OldSchoolArtist> artists = new List<OldSchoolArtist>();
            List<SyndicationItem> feedItems = new List<SyndicationItem>();

            //Getting the data from the db
            using (var db = new OldSchoolBeatsContext())
            {
                //Selecting the first 50 entries
                artists = db.OldSchoolArtists.OrderBy(a=>a.CreatedAt).Take(50).ToList();
            }

            foreach (var artist in artists)
            {
                var rssEntry = new SyndicationItem()
                {
                    Title = new TextSyndicationContent(artist.Artist, 
                                         TextSyndicationContentKind.Plaintext),
                    Id = new Guid().ToString(),
                    PublishDate = DateTime.Now,
                    Summary = new TextSyndicationContent(

                        string.Format("{0} was active between {1} 
                        and was added to our database {2}.", artist.Artist, 
                        artist.YearsArchive, artist.CreatedAt),
                        TextSyndicationContentKind.Plaintext

                        ),
                    Copyright = new TextSyndicationContent
                                ("ALLMUSIC.COM", TextSyndicationContentKind.Plaintext)
                };

                feedItems.Add(rssEntry);
            }

            //Write our feed to a string builder
            //using a XML-Writer instance
            var sb = new StringBuilder();

            XmlWriter w = XmlWriter.Create(sb);

            feed.SaveAsRss20(w);

            w.Flush();
            w.Close();

            var response = new HttpResponseMessage(HttpStatusCode.OK);

            //The standard encoding for the feed is UTF-16, which is Unicode, little-endian encoding
            //And the media-type is "application/rss+xml"
            response.Content = new StringContent(sb.ToString(), 
            Encoding.Unicode, "application/rss+xml");

            return response;
        }
    }
}

In the first few lines, you can see how to obtain the current user (if the user has been authenticated). If not, the current user is null (currentMobileServicesUser). On the next lines, an instance of the SyndicationFeed class is created.

This class allows you to create Atom or RSS-Feeds in a very simple way, that way you don’t have to fiddle around with xml-documents. First the feed needs to be created, then the items and the last step is to write the feed to an XML writer.

Then a new instance of the OldSchoolBeatsContext is created. This is the class that allows us, to access the data (our tables) using Entity Framework. Using LINQ, we just take the 50 latest entries from the database. One line of code that makes us happy.

The last third of the code handles the generation of the RSS 2.0 feed. To output the content of the XMLWriter instance, we use a StringBuilder. Please don’t forget to flush the contents of the writer and to close it. This ensures that the underlying stream is actually written into the StringBuilder. The rest of the code returns a new HttpResponseMessage with a status code of 200 (which basically means that everything is ok). The desired return type is “application/rss+xml” which is the mime-type used for a RSS feeds. Even if we have no data in our OldSchoolArtists table, we still get a response of 200 and the basic construct for an valid RSS 2.0 feed.

If you hit F5 now to debug the managed service locally and you type in the following URL => http://localhost:9215/api/OldschoolFeeds (the port number 9215 should be different from mine) in Internet Explorer for example, you will get the RSS-Subscription view:

Image 4

As long as you don’t delete the table “OldSchoolArtists”, everything should work just fine.

In the next and last part, we will create the universal app and implement the complete set of crud operations on Windows 8.1 and Windows Phone 8.1.

You can download the source here: OldSchoolBeats on GitHub

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)