April 2012 - Posts - Jon Galloway

April 2012 - Posts

Upcoming Web Camps

We've got some great, free Web Camps headed your way!

Web Camps are free, fun, no-fluff events for developers, by developers. Show up for the day, leave infused with a crazy amount of web dev info. Did I mention these are free?

My teammate Brady Gaster has put together some phenomenal new content, and I'm really looking forward to presenting at some of these.

Web Camps Locations

So far the following locations have been announced:

Location Date Registration Notes
Brussels, Belgium 3-May-12 Register Here With Brady Gaster and Matthew Osborn... and there's still room!
Waltham, MA 10-May-12 Register Here I'll be here! Also starring Chris Bowen and Jim O'Neil!
Mountain View, CA 14-May-12 Register Here With the amazing Doris Chen!
Denver, CO 18-May-12 Register Here Also Doris Chen!
Phoenix, AZ 25-May-12 Register Here Also Doris Chen! Wow, she's busy!
Mountain View, CA 29-May-12 Register Here I'll be here! Maybe someone else, too.

There are a bunch more that are in the works but not quite ready to be announced yet - I'll update here, but the best place to keep up to date is at http://www.devcamps.ms/web

Oh, and I believe there's still room at the Web Camp in Brussels on May 3.

Web Camps Content

I've reviewed and contributed a bit to the Web Camps content that Brady's put together, and it's really, really good. There's a ton of information packed in. Here's an overview of the agenda (see the registration link for the exact agenda at each location):

  • Welcome Back to the Microsoft Web Stack
  • Integrating Your Site with Internet Explorer 9
  • Top 10 Things You Didn't Know about WebMatrix 2
  • Creating Rich HTML 5 Experiences
  • Building Web Sites Using ASP.NET 4.5
  • Building a Service Layer with ASP.NET Web API
  • Deploying ASP.NET Apps to the Cloud

You can read more about those topic at http://www.devcamps.ms/web/agenda.

Infomercial!

Now if you're almost convinced, but on the edge, and you need a video to push you over the top, you watch Brady and me announcing the Web Camps tour on Web Camps TV a few weeks ago:

Yes, if you read my blog you'll have noticed that this video is a repeat. That's how infomercials work.

Posted by Jon Galloway | with no comments
Filed under:

Windows 8 and ASP.NET Web API - Part 1 - Getting Started

Many of the key Windows 8 Metro Style application features either require or can greatly benefit from a connection to online services. ASP.NET Web API is a great fit for these services, as it's tightly focused around providing HTTP services to applications. I'm starting a series that will look at how to leverage ASP.NET Web API services from Windows 8 applications.

In this first post in the series, we'll begin with a simple C# Windows 8 Metro Style application that displays data from the ASP.NET Web API Contact Manager sample. Once we've got the basics locked down, we'll move on to some more complex topics. I'm thinking Live Tiles and Notifications, but I'm interested in your ideas of where to go next, so please let me know in the comments.

The ASP.NET Web API Contact Manager sample

I thought it would be simplest to start with an official, tried and true Web API sample that's been around since the early days of WCF Web API - the Contact Manager Sample. You can download the code here: http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d

This code is originally written for Visual Studio 2010, but I'm going to be working on Visual Studio 11 Beta running on Windows 8 Consumer Preview, so I ran through the upgrade. There's an alert which says "One or more Web Application projects in this solution require SQL Server Express. You will need to download and install the appropriate version of SQL Server Express for these projects to work." A quick look at the code, however shows that all the data is in-memory, so we can ignore it. If we keep with this code for long, we can just remove the offending NuGet package, but let's not let that slow us down just yet.

Running the application shows that the application is indeed working.

2012-04-27_01h26_16

The HTML client page is making an .getJSON() call back to the Web API service, which returns a list of contacts in JSON format, then uses jQuery templating to display the contacts in HTML format. That jQuery templating should probably be updated to use the newer JSRender system, but it doesn't really matter for this example, since we're just concerned about the services, not the HTML client.

Looking at the ASP.NET Web API's services using F12 developer tools

We're going to be using Fiddler2 in a bit, but since the simplest way to view the output of the Web API's JSON services is in a browser. In IE, you do that by pressing the F12 hotkey to display developer tools - it looks like this:

2012-04-27_02h01_20

Now switch to the Network view (or your browser's equivalent), start monitoring, and browse to /contacts (in my case the full URL is http://localhost:33936/contacts, your port number will vary). IE prompts you to download the JSON file and the browser's address bar goes back to the previous. That's a little wacky - other browsers display the JSON as text - but the service call response is included in the results. Clicking on it to bring up the detailed view and showing the response body shows the JSON data:

2012-04-27_02h09_00

The JSON data returned is as follows (I removed some of the contacts from the list for brevity):

[ { "Address" : "1 Microsoft Way",
    "City" : "Redmond",
    "ContactId" : 1,
    "Email" : "example@microsoft.com",
    "Name" : "Glenn Block",
    "Self" : "contact/1",
    "State" : "Washington",
    "Twitter" : "gblock",
    "Zip" : "98112"
  },
  { "Address" : "1 Microsoft Way",
    "City" : "Redmond",
    "ContactId" : 2,
    "Email" : "example@microsoft.com",
    "Name" : "Howard Dierking",
    "Self" : "contact/2",
    "State" : "Washington",
    "Twitter" : "howard_dierking",
    "Zip" : "98112"
  },
  { "Address" : "1 Microsoft Way",
    "City" : "Redmond",
    "ContactId" : 3,
    "Email" : "example@microsoft.com",
    "Name" : "Yavor Georgiev",
    "Self" : "contact/3",
    "State" : "Washington",
    "Twitter" : "digthepony",
    "Zip" : "98112"
  }]

That content's being returned from the ContactsController's Get action, which just returns a Queryable list:

public IQueryable Get()
{
    return this.repository.GetAll().AsQueryable();
}

Out of the box, ASP.NET Web API can format data in JSON and XML format, so the output is automatic depending on content negotiation. If you're familiar with ASP.NET Web API, this is all pretty standard stuff. If you're not, I recommend the ASP.NET Web API content section at http://asp.net/web-api and my previous blog / screencast series on getting started with ASP.NET Web API.

The point is that this sample is producing JSON data that we can display in our Windows 8 Metro application.

Creating a Windows 8 Metro style application using the Blank template

To create the Windows 8 Metro application, add a new project using the File / Add / New Project... dialog. Select the Visual C# / Windows Metro Style section, then pick the Blank Application template. I called mine ContactManagerMetro because I have no imagination.

2012-04-27_00h49_24

Why the Blank Application template? Good question. I started with the Split Application template, but it has existing data structures which are hierarchical (since the Split Application helps with navigating structured content), so it wasn't a good fit. I think the Blank Application template is a good start since it's nice and simple.

This application is, as promised, rather blank. The main form is even called BlankPage.xaml, which while being rather descriptive of the initial state, seems unlikely to remain accurate for very long in most cases. Since we're just proving concepts at this point, though, I'm going to grit my teeth and leave the name as BlankPage.xaml. Focus.

Writing the Metro Application XAML

We've got a lot of options for how to display the contact information, but I think a good start is using the same kind of display that the original HTML view used. In the Metro XAML land, that's usually done using a ListView. Inside BlankPage.xaml's empty grid, I'm going to add the following ListView markup:

<GridView x:Name="ContactList">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel Width="200" Height="150" Margin="10" Background="#FF161C8F">
                <TextBlock Text="{Binding Name}" FontSize="24" />
                <TextBlock Text="{Binding Address}" />
                <TextBlock Text="{Binding City}" />
                <TextBlock Text="{Binding State}" />
                <TextBlock Text="{Binding Zip}" />
                <TextBlock Text="{Binding Twitter}" />
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

This is pretty rudimentary, we'll clean it up later. The main reason I'm writing it now is to make sure I know what I'll be binding to, and for the above TextBlock binding values I just based the values off the contact properties returned by the service.

Calling the Web API service from our Metro Application

Calling the service is actually pretty straightforward. First, I'll use the System.Net.Http.HttpClient to call the service. As all external calls in WinRT are async, I need to handle that. Fortunately the async/await keywords make that really easy.

Since our service returns JSON, I'm going to leverage the utility classes in the Windows.Data.Json namespace to parse it. The code is a little repetitive and could definitely use some refactoring, but it handles the job of mapping JSON values to an anonymous object. Tim Heuer recently blogged about using that with anonymous type binding, and I liked his approach.

With all the plumbing in place, I'll call this GetContacts() method from my OnNavigatedTo event.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    GetContacts();
}

public async void GetContacts()
{
    var serviceuri = "http://localhost:33936/contacts";
    var client = new System.Net.Http.HttpClient();

    var response = await client.GetAsync(serviceuri);
    if (response.IsSuccessStatusCode)
    {
        var data = await response.Content.ReadAsStringAsync();
        var contacts = JsonArray.Parse(data);

        var qry = from m in contacts
            select new
            {
                Name = m.GetObject()["Name"].GetString(),
                Address = m.GetObject()["Address"].GetString(),
                City = m.GetObject()["City"].GetString(),
                State = m.GetObject()["State"].GetString(),
                Zip = m.GetObject()["Zip"].GetString(),
                Twitter = m.GetObject()["Twitter"].GetString(),
            };

        ContactList.ItemsSource = qry;
    }
}

This calls into our service and displays the following data:

Screenshot

Hurrah! We got data from our service and viewed it in the app. It's pretty ugly, though. Let's clean up the formatting a bit so it matches the original app a little better. I'm using the underappreciated <Run> XAML element for that:

<GridView x:Name="ContactList">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel Width="250" Height="150" Margin="10" Background="#FF161C8F">
                <TextBlock Text="{Binding Name}" FontSize="28" Margin="10,20,10,0" />
                <TextBlock Margin="10,0">
                    <Run Text="{Binding Address}" />, <Run Text="{Binding City}" />
                </TextBlock>
                <TextBlock Margin="10,0">
                    <Run Text="{Binding State}" /> <Run Text="{Binding Zip}" />
                </TextBlock>
                <TextBlock Margin="10,0">
                    @<Run Text="{Binding Twitter}" />
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

That at least organizes the text a bit:

Screenshot (2)

And that's at least a decent start. Questions? Where should we go next?

Posted by Jon Galloway | with no comments

ASP.NET MVC Authentication - Global Authentication and Allow Anonymous

As I was recently updating the Wrox Professional ASP.NET book for ASP.NET MVC 4, I thought about some of the common questions, tip, and tricks I've seen over the past few years, and thought it was time for a... quick blog series! Let's start with Global Authentication.

ASP.NET MVC has had an Account Controller since the ASP.NET MVC 1.0 preview releases; it handles login and registration. That, by itself, just allows users to get logged in - it doesn't do anything to restrict access. That's where the AuthorizeAttribute comes into play. AuthorizeAttribute is a Filter attribute which can be placed on ASP.NET MVC actions or entire controllers to prevent unauthorized access. Attempting to access a restricted controller action when you're not authorized redirects you to login, as I previously described in quite gory detail in a previous post titled Looking at how the ASP.NET MVC Authorize interacts with ASP.NET Forms Authorization.

Reminder: Don't use web.config to restrict access, use [Authorize]

Note: This is old news to MVC veterans, but bears repeating because it continues to be a common question and is really important to get right.

In ASP.NET Web Forms, requests mapped to physical files. There's an <authorization> element  in web.config which can be used to restrict file-based access. So this worked well for ASP.NET Web Forms and file-based authorization in general.

But it's a very bad idea to use web.config based authorization in ASP.NET MVC, because URL's map to actions via routing, which can change. You may have multiple routes that map to the same controller action, or you may change routes over time. AuthorizeAttribute was built specifically for this purpose, because you can place your security directly on the resource (the action or controller). Change the routes all you want, the authorization rules go along with the actions.

Another interesting note here is that, since ASP.NET Web Forms has supported routing since ASP.NET 4, you need to pay closer attention to securing routes there as well. K. Scott Allen discussed that in an MSDN Magazine article a few years ago, Routing with ASP.NET Web Forms.

The progression of global authentication in ASP.NET MVC

The AuthorizeAttribute works pretty well, but you have to put it on every controller (or action, if you need to be that granular) that needs to be secured. That's tedious and error prone, and if you forget it, you've opened your site up to anonymous access. In many cases, it's preferable to restrict access to the entire site except for the the Login and Register actions. That's become a little easier with each release, to the point where in ASP.NET MVC 4 I think it's finally about right.

Rick Anderson wrote two comprehensive posts on this - and authorization in ASP.NET MVC in general - in a pair of posts covering security in ASP.NET MVC:

ASP.NET MVC 1 and 2 - Custom Controller Base

In the first post, Rick explains that prior to ASP.NET MVC 3, the recommended approach was to create a custom Controller base class with an [Authorize] attribute applied. This probably sounds more complicated than it is, because it's really easy:

  1. Right-click the Controllers folder and add a new Controller. Call it something like AuthorizedController.
  2. Delete the Index action.
  3. Add the [Authorize] attribute to the class.
  4. Clean up the Using block at the top if you care about that kind of thing.

End result:

using System.Web.Mvc;

namespace InstantMonkeysOnline.Controllers
{
    [Authorize]
    public class AuthorizedController : Controller
    {
    }
}

Now you can use this AuthorizedController base class for any other controllers in your application. Changing the HomeController base class to inherit from AuthorizedController will require authorization to view the site home:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace InstantMonkeysOnline.Controllers
{
    public class HomeController : AuthorizedController
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            return View();
        }

        //More actions here
    }
}

The downside is that you have to remember to do this, so unless you change the T4 templates, you're setting yourself up for an easy mistake down the road.

ASP.NET MVC 3 - Global Action Filters

ASP.NET MVC 3 made it easy to apply an action filter to all actions in your application. If you look in the Global.asax in an new ASP.NET MVC 3 (or later) application, you'll see a RegisterGlobalFilters method.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

To require authorization throughout your application, you could just register AuthorizationAttribute, right?

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new AuthorizeAttribute());
}

Unfortunately, this works a little too well - it's global, so users can't login. But, really, really secure, right?

Rick proposed a custom LoginAuthorizeAttribute which inherited from AuthorizeAttribute but added an exception for the AccountController, but Levi Broderick (an ASP.NET team member who's a whiz with web security) recommended using a filter to whitelist actions which should be available for anonymous access.

using System.Web.Mvc;
using MvcGlobalAuthorize.Controllers;

namespace MvcGlobalAuthorize.Filters {
    public sealed class LogonAuthorize : AuthorizeAttribute {
        public override void OnAuthorization(AuthorizationContext filterContext) {
            bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
            || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
            if (!skipAuthorization) {
                base.OnAuthorization(filterContext);
            }
        }
    }
}

So now you'd register LogonAuthorize as a global filter, and to allow access to an action, you'll need that AllowAnonymousAttribute. Since it's just a marker attribute, there's no actual code - just attribute usage settings.

using System;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, 
                AllowMultiple = false, Inherited = true)]
public sealed class AllowAnonymousAttribute : Attribute { }

ASP.NET MVC 4 and the AllowAnonymous attribute

The good news is that this is even easier in ASP.NET MVC 4, because it's baked in. By baked in, I mean that:

  • There's a built-in AllowAnonymousAttribute in the the System.Web.Mvc namespace which whitelists actions for anonymous access
  • The AuthorizeAttribute filter has built-in logic that allows access to actions decorated with the AllowAnonymousAttribute

That means that you can just register the AuthorizeAttribute as a global filter and put the AllowAnonymousAttribute on any actions that should be public.

If you use the AllowAnonymousAttribute without registering AuthorizeAttribute there's no effect. For that reason, the default AccountController in a new ASP.NET MVC 4 project has [AllowAnonymous] on all the actions that should always be public:

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()

    [AllowAnonymous]
    [HttpPost]
    public JsonResult JsonLogin(LoginModel model, string returnUrl)

    [AllowAnonymous]
    [HttpPost]
    public ActionResult Login(LoginModel model, string returnUrl)

    public ActionResult LogOff()

    [AllowAnonymous]
    public ActionResult Register()

    [AllowAnonymous]
    [HttpPost]
    public ActionResult JsonRegister(RegisterModel model)

    [AllowAnonymous]
    [HttpPost]
    public ActionResult Register(RegisterModel model)

    public ActionResult ChangePassword()

    [HttpPost]
    public ActionResult ChangePassword(ChangePasswordModel model)

    public ActionResult ChangePasswordSuccess()
}

That works because, as mentioned above, the AuthorizeAttribute has the following logic (as you can see from the code on CodePlex):

bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(
		typeof(AllowAnonymousAttribute), inherit: true)
	|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(
		typeof(AllowAnonymousAttribute), inherit: true);

if (skipAuthorization)
{
    return;
}

Note: I actually started looking into this in detail because I was wondering how the AllowAnonymousAttribute was able to bypass the Authorization check, and was surprised to see that it didn't have any code at all. I wasn't alone here, I noticed David Hayden looked into this as well.

If you're interested in more information on ASP.NET MVC security and the history of the AnonymousAttribute, I highly recommend Rick's posts listed above. He goes into a lot more detail - with some excellent input from Levi - on what not to do (e.g. put security logic into routing) and further considerations like requiring HTTPS globally.

Posted by Jon Galloway | 10 comment(s)
Filed under:

I've joined the Windows Azure technical evangelist team

I've been at Microsoft for a little over two years now, working in groups that focused primarily on publishing online content for developers. In addition to the obvious things, there's a lot of work that goes on behind the scenes in creating and maintaining content  - maintaining and improving existing content, planning content for unreleased platforms and products, handling dozens of spoken languages and several programming languages, etc. It's been a pleasure working with some real professionals. I've also enjoyed working in a small but dynamic group that's focused on the developer community. During that time I had two excellent bosses, Scott Hanselman and Pete Brown. Both really made it fun to show up to work every day. Well, I work from home, but still.

I'm excited about my new position in the Windows Azure technical evangelist team.

Wait, what? Azure?

Yep, Azure. Let me explain why.

Azure Application Platform Team includes ASP.NET, IIS, etc.

First, you'll recall that Scott Guthrie heads the Azure Application Platform team, and that group includes ASP.NET and IIS. In the year since that transition, I've been really happy with where I've seen Microsoft's web platform going. The ASP.NET team has been cranking out some great stuff for the ASP.NET 4.5 / ASP.NET MVC 4 / ASP.NET Web Pages 2 wave (easier to just call it ASP.NET vNext). Oh, and they just open sourced a whole lot of code. So if anyone was concerned that ASP.NET would stall out in this new organization, I think this past year would allay that fear.

Azure as a good influence on Microsoft

And in fact, it seems like the influence of running Azure as a hosting platform has opened Microsoft's web development horizons a good amount. We've got people like Glenn Block working with Node.js, Microsoft shipping code on GitHub (all the Azure sdk's are on GitHub), Hadoop support on both Azure and Windows Server, etc. So if anything, Azure is really broadening Microsoft's perspective on web development. I hadn't expected that at all.

Azure future

Well. All I can say here is that I'm extremely excited about where Azure is going as a platform. As Scott Guthrie said in MSDN Flash recently, "You will see even more significant updates and features in Windows Azure in the months ahead." There are a lot of things coming together here that are making Azure very interesting for me as a developer, and I want to be in on it. Stay tuned.

Windows Azure Technical Evangelist team

This is an cool team. I'm helping (new Microsoft employee) Brady Gaster with this summer's Web Camps, learning some interesting Windows 8 dev from Nick Harris, got to meet up with Nathan Totten (I'd used his Facebook SDK in the past), and I'm just getting started. Oh, and Cory Fowler just joined up too, focusing on the open source community on Azure including PHP and Node.js. And lots of other smart folks, all focusing on different applications of Azure and the Azure application platform. James Conard has put a really good team together, and it's really energizing to be a part of it.

Nick and Nate just took over the Cloud Cover show on Channel 9 and interviewed me, along with the other three new team members: Cloud Cover - Episode 76 - Meet our new additions to the Windows Azure Technical Evangelist Team (I'm on around 14:40).

What's new for Jon

I'll be continuing to focus on ASP.NET as a platform. I like ASP.NET, and I like helping other people who are using it. Azure is a good place to put ASP.NET apps, so more ASP.NET apps helps Azure. So that means I'll continue to do thing's I've been doing in the past - blogging, speaking, writing, tutorials, screencasts about ASP.NET. But with more options for scale, travel budget, opportunities for collaboration with other groups, etc.

For example, I'll be speaking at a Web Camp in Boston on May 10 as part of the Web Camps tour that Brady's putting together. Brady invited me on Web Camps TV to help introduce Web Camps 2012:

Jon Galloway Helps Introduce Web Camps 2012

I've been doing some behind the scenes work on the ASP.NET site to make content easier to find and consume (e.g. HTML5 video support, input on responsive design). I also help with content for ASP.NET releases, like edits and publishing the ASP.NET MVC release notes, setting up things like the ASP.NET Web API content area, etc. That won't change.

So my focus stays on ASP.NET as a platform - whether you host it on Azure, IIS, or wherever else you crazy kids decide to put it.

But, as I said, I joined the Azure evangelist team because I'm excited abou it, so of course I'll be using it and talking about it as I do. For intstance, I'm thinking there are a lot of opportunities to spin up sample apps and services in Azure to show what I'm talking about.

More Posts