Cloudy With a Chance of Mobile: Building Our Data Model & API

Interested in having a web site that supports user-specific data? Perfect, use Asp.Net and the built in membership providers. Want to put it in the cloud? Sweet, jump on the Azure bandwagon. Want to easily define your data model and store it? No worries, EF Code First will make you cry, you love it so much. Want to access that data from Windows Phone? Well, my friend, you’ve come to the right place. If you want to follow along from the beginning, please check out the first post in the series.

With my projects roughly set up the way I’d like them to be I can now start building my data model using Entity Framework or “EF”.  I’ll use the model definition to quickly scaffold some UI and add some data to my project.

I will then expose that data via the new Web API available in Mvc 4.  Though I have two solutions set up, I’ll only be working in the Mvc 4 project for this tutorial.  A reminder that if you’re opening the IDE to follow along after a break you’ll need to open it up in Administrator mode for the Azure environment to run correctly.

Our Data Class

To keep things simple I’m going to use a single entity class – and ultimately a single table – for this exercise.  In the Mvc 4 project, use the Solution Explorer to locate and then right-click on the Models folder to add a new class called PhoneNumberEntry.  The class will look like the following:

    public class PhoneNumberEntry
    {
        public int PhoneNumberEntryId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string PhoneNumber { get; set; }
        public string UserName { get; set; }
    }

Hey, don’t judge. I said I was keeping it simple. Winking smile

Next, I need to tell EF how to create the database, namely, I have to tell it what tables to create and of which entity. I do this through inheritance and attributes on our classes.  You can put this definition in the same file as the PhoneNumberEntry class.  Again, it’s very light weight.

    public class ContactContext: DbContext
    {
        public DbSet<PhoneNumberEntry> PhoneNumberEntries { get; set; }
    }

Perfect, now I’m rolling. To create the UI, I’m simply going to use the tooling that’s built into the MVC Framework through Visual Studio 2010. In order to fully leverage this, I need to compile my classes so that the IDE can reflect on my project and show me a list of them.  I like to use the keyboard shortcut Shift + Ctrl + B to build.

Building the Views

With my project compiled, I right-click on the Controllers folder in Project Explorer and select Add –> Controller. I name my controller appropriately, select my PhoneNumberEntry class and name a new Data Context Class.  I choose the Controller with read/write actions and views, using Entity Framework as the template.

image

The tooling builds my controller and scaffolds out my views for me.

I only want members who have registered to create entries, and I want to each user to have their own list. I created a UserName property on my model, so I now need to deal with that field on my own. In my Create and Edit views, I remove the UserName field. Here’s an example of what that HTML looked like before I removed it:

image

With that out of the way (in both Create and Edit) I need to update my controller accordingly. I open PhoneNumberEntryController in the Controllers folder and add the Authorize attribute to my class.

    [Authorize]
    public class PhoneNumberEntryController : Controller
    {
        // ...rest of class here
    }

By attributing the controller in this way (at the class level), I am telling the Asp.Net runtime that any user who accesses any action on this controller needs to be logged in using the authentication scheme of the site.  Now, all users who try to navigate to any of my Phone Numbers pages will first be prompted to log in.

image

Driven By the Logged in User

Next, I want to make sure that the user only ever sees the phone numbers that they create.  The index method needs to be adjusted to only return the appropriate entries.

    public ActionResult Index()
    {
        string username = User.Identity.Name;

        var phoneNumbers = db.PhoneNumberEntries
            .Where(p => p.UserName == username)
            .ToList();

        return View(phoneNumbers);
    }

In the Create and Edit methods decorated with the HttpPost attribute (these are the methods that accept the PhoneNumberEntry parameters from the form) I add a bit of code to capture the user’s login name and store that in the model.

    [HttpPost]
    public ActionResult Create(PhoneNumberEntry phonenumberentry)
    {
        string username = User.Identity.Name;
        phonenumberentry.UserName = username;

        if (ModelState.IsValid)
        {
            db.PhoneNumberEntries.Add(phonenumberentry);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(phonenumberentry);
    }
> **Important note**: There are many more security considerations to take and I am only demonstrating some bare minimums. In a real-world scenario you would use a repository outside of the controller and would do the appropriate checks to protect your data at various levels of your project. Particularly, any code to retrieve or modify the data should have checks in place to ensure the user is authorized to view or modify the resource in question.  As an exercise to the reader, work through the PhoneNumberEntryController and firm up the user access/rights to a better degree. Everything should be set here to capture some data, but I want to be able to easily access these bits of UI.  I open up my _Layout.cshtml file, located in Views\Shared in the Solution Explorer and modify the snippet of code that creates the menu elements.  When finished, it looks like so:
    <nav>
        <ul id="menu">
            <li>@Html.ActionLink("Home", "Index", "Home")</li>
            <li>@Html.ActionLink("About", "About", "Home")</li>
            <li>@Html.ActionLink("Phone Numbers", "Index", "PhoneNumberEntry")</li>
            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
        </ul>
    </nav>

The LI elements are formatted through the default site template and the UL is used as a wrapper to generate the menu at the top of the page. The ActionLink helper method renders an anchor tag for the specified controller/action.

Getting Some Data In There

Before I move onto the API portion of this exercise, I press F5 to run my site and use the newly created Phone Numbers menu to get at the UI the framework generated for me.  I add several entries as you can see below.

image

Now, I want to go one step further. This is about accessing the data for a specific user, so I want to have some other data in there as well to prove out that we can isolate the data and make use of the Authentication providers in Asp.Net.  I create another user and add more entries as I did above, and you can see in the database now how there is data in there for two users.

image

I now have data specific to a couple of users and can build out the service piece.

Cutting a Web API Controller

This piece is really easy and uses the tooling and templates from the MVC Framework.  I add a new folder called Api to my Controllers folder and then right-click on the Api folder and select Add –> Controller.  I name it PhoneNumberEntryController and select the Empty Api controller as the scaffolder. Even though it’s the same name, it ends up in a different namespace so everyone’s happy.

image

Much like the controller returning a view, I want the ApiController to only allow authenticated requests, and I want the method to return only phone numbers for the current user.

    [Authorize]
    public class PhoneNumberEntryController : ApiController
    {
        private CloudyWebSiteContext db = new CloudyWebSiteContext();

        public ICollection<PhoneNumberEntry> Get()
        {
            string username = ControllerContext.Request.GetUserPrincipal().Identity.Name;

            var phoneNumbers = db.PhoneNumberEntries
                .Where(p => p.UserName == username)
                .ToList();

            return phoneNumbers;

        }
    }

There’s one more thing I want to do: I want to suppress the Xml formatter that is on by default in WebAPI.  By turning it off, the only remaining default serializer is Json.  Glenn Block shows us the most performant way to do this in our Global.asax’s Application_Start menthod:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

People. We are now awesomely rocking.  I will coin the term “awesrocking” because of the awesomeness here.

imageTesting Out the Api

This is the part where I could start to hit some roadblocks if I didn’t have the right tools. I love Fiddler and use it first whenever I’m, uh…fiddling around, but I can’t use Fiddler to poke around the API because I need a user to see what I’m doing and authentication is forms based in this context. I can’t use IE efficiently because every time I get a Json document returned it prompts me to open the file of an unknown file type. I could use Notepad here (or a registry hack), I know, but it’s a pain and I like to see my data all nicely formatted Winking smile.

FireFox to the rescue, along with a little helper plugin called JsonView.  In Visual Studio 11 this will be even easier because I can choose the browser to launch, rather than launching a separate browser or setting the OS default.  Regardless, I run the app in FireFox, log in to my site, then I hit http://127.0.0.1:81/api/phonenumberentry to see the data. JsonView takes over and I see my phone numbers as we expect.

You can see the result in the image to the right.

Wrapping Up and Next Steps

Okay, here’s the quick breakdown for the steps we have taken to this point:

  1. Added our model (class)
  2. Added our data context
  3. Scaffolded our views
  4. Secured our views
  5. Tied the data entry and loading to specific users
  6. Added some data
  7. Created a Web API controller
  8. Secured the controller and started returning the correct data

 

With these things in place, I can now start work on my phone client. Our project is already set, so we can get to the heavy lifting right away! Stay tuned for the next post where I’ll get the phone client lined up to consume the data and display it.  Later on we’ll talk about some things we can do to better improve the code and get us closer to best practices.