Tuesday, March 29, 2011

Presentation Downloads

Presentation downloads are (finally) up!

The PLINQO presentation will be up some time next week.

Enjoy!
Tom

Friday, March 18, 2011

OAuth 2.0 for MVC, Two Legged Implementation

OAuth 1.0 was one complicated beast. The OAuth 2.0 spec greatly simplified things, but that also had the wonderful side effect of rending all of our old OAuth 1.0 code obsolete. They say that "the only thing a pioneer gets is an arrow in the back," I disagree, I say "the thing that only a pioneer gets to have is an adventure."

For example, I got to help write this wonderful, cutting edge, open source, OAuth 2.0 implementation for MVC!

OAuth 2.0 Overview

OAuth is all about tokens. You start by getting a Request Token from the server, and then using that to secure your login information. When you have successfully logged in you will be given a role/permission specific Access Token, you will then submit this token with all of your future requests. You will also get a Refresh Token with your Access Token. Once your Access Token has expired, you can then submit your Refresh Token to get a new pair of Access and Request Tokens.

Two Legged vs Three Legged

A two legged implementation is rather straight forward, you log into the server you are trying to access. A three legged implementation allows you to gain access to a resource by authentication with a third party server.  For the time being this project only supports two legged authentication.

Implementation

You must implement four classes to use this library:

  1. OAuthIdentityBase
  2. OAuthPrincipalBase
  3. OAuthProviderBase
  4. OAuthServiceBase

The first three are very small classes, requiring only a few short lines of code. The Service is the work horse where most of your code will go, but even then it only requires the implementation of four methods.

public abstract class OAuthServiceBase : ProviderBase, IOAuthService
{
    public static IOAuthService Instance { get; set; }
    public abstract OAuthResponse RequestToken();
    public abstract OAuthResponse AccessToken(string requestToken,
        string grantType, string userName, string password, bool persistent);
    public abstract OAuthResponse RefreshToken(string refreshToken);
    public abstract bool UnauthorizeToken(string token);
}

Then of course you will need to update your Web.config:

<configuration>
  <configSections>
    <section name="oauth" type="OAuth2.Mvc.Configuration.OAuthSection, OAuth2.Mvc, Version=1.0.0.0, Culture=neutral"/>
  </configSections>
  <oauth defaultProvider="DemoProvider" defaultService="DemoService">
    <providers>
      <add name="DemoProvider" type="OAuth2.Demo.OAuth.DemoProvider, OAuth2.Demo" />
    </providers>
    <services>
      <add name="DemoService" type="OAuth2.Demo.OAuth.DemoService, OAuth2.Demo" />
    </services>
  </oauth>
  <system.web>
    <httpModules>
      <add name="OAuthAuthentication" type="OAuth2.Mvc.Module.OAuthAuthenticationModule, OAuth2.Mvc, Version=1.0.0.0, Culture=neutral"/>
    </httpModules>
  </system.web>
</configuration>

Securing Your Pages

That's the easy part, just add the MVC Authorize Attribute to any actions or controllers that you want to secure.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
 
    [Authorize]
    public ActionResult Secure()
    {
        return View();
    }
}

The Demo API in Action

  • /oauth/requesttoken
    • Request Params
      • None
    • Result
      • RequestToken = a028f1895cc548af9de744f63d283f6e
      • Expires = 300
      • Success = true
  • /oauth/accesstoken
    • Request Params
      • oauth_token = a028f1895cc548af9de744f63d283f6e
      • username = tom
      • password = c4e5995d4cb8b26970336b956054ac1be9cc50b3
    • Result
      • AccessToken = 3b23ee5f128a45c88e657ecc74c41bbc
      • Expires = 300
      • RefreshToken = 85126a53bca940f1ae7c9d797f63a274
      • Success = true
  • /oauth/refreshtoken
    • Request Params
      • refreshToken = 85126a53bca940f1ae7c9d797f63a274
    • Result
      • AccessToken = 8cfc317af6ed45b2b065a8fa5da3ba81
      • Expires = 300
      • RefreshToken = d0b4a8898d974e939ca83b55cfeabcac
      • Success = true
  • /oauth/unauthorize
    • Request Params
      • oauth_token = 8cfc317af6ed45b2b065a8fa5da3ba81
    • Result
      • Success = true

Additional Resources

Happy authenticating!
~ Tom

Friday, March 11, 2011

CodeSmith 2011 User Group Tour

The CodeSmith Tools are hitting the road (and even the skies) to talk about .NET technology all around the US!
Want us to speak at your local user group? Just drop me a line!

We will post again each month with updates and additional details, so stay tuned!

Dates

  • Oklahoma
    • April 4th (Monday) - Oklahoma City DNUG - PLINQO: Advanced LINQ to SQL
  • Arkansas
    • March 25th (Friday) - North West Arkansas TechFest 2011 - Attack of the Cloud
    • April 11th (Monday) - Fort Smith DNUG - PLINQO: Advanced LINQ to SQL
    • April 12th (Tuesday) - North West Arkansas DNUG - TBA
    • April 13th (Wednesday) - North West Arkansas SQL Server UG - PLINQO: Advanced LINQ to SQL
    • April 14th (Thursday) - Little Rock DNUG - Using Embedded QA to Build Rock-Solid Software
  • New Mexico
    • May 5th (Thursday) - New Mexico DNUG - Attack of the Cloud
  • Iowa
    • May 9th (Monday) - Cedar Rapids DNUG - Code Generation
    • August 4th (Thursday) - Des Moines DNUG - Using Embedded QA to Build Rock-Solid Software
  • Texas
    • May 11th (Wednesday) - DFW Connected Systems UG - PLINQO: Advanced LINQ to SQL
  • Florida
    • May 26th (Thursday) - Memphis DNUG - Code Generation
    • June 1st (Wednesday) - Space Coast DNUG - PLINQO: Advanced LINQ to SQL
    • June 2nd (Thursday) - Tallahassee DNUG - Attack of the Cloud
    • June 7th (Tuesday) - Deerfield Beach DNUG - Code Generation
  • New York
    • July 7th (Thursday) - Long Island DNUG - Code Generation
    • TBD - Fairfield DNUG - Code Generation

Topics

  • Attack of the Cloud
    • Cloud computing is great, but what do we put in the cloud? The web is advancing at an incredible pace and it’s time to start building true Web Applications, not just web sites! Web Apps shake off the constraints of operating system specific frameworks and free developers to work in an open standards based environment. This session will cover a variety of topics ranging from ASP.NET MVC development, unit testing, REST APIs, JSON, JQuery, ExtJS, tips and tricks, lessons learned, and more. It will conclude with building a sample blog reader Web App, and then deploying that to Windows Azure.
  • Code Generation
    • Code generation is a powerful practice that allows you produce higher-quality, more consistent code in less time. This helps remove the mundane and repetitive parts of programming, allowing developers to focus their efforts on more important tasks, and saving companies time and money. Code generation enables you to: efficiently reduce repetitive coding, generate code in less time with fewer bugs, and produce consistent code that adheres to your standards.
  • Using Embedded QA to Build Rock-Solid Software
    • Without an automated means to collect errors from deployed applications, how can you know that your software is performing as expected? Embedded QA can be used to augment your own internal QA efforts, greatly increasing both the effectiveness of your testing and overall stability of your applications. As Jeff Atwood phrased it, "If you're waiting around for users to tell you about problems with your website or application, you're only seeing a tiny fraction of all the problems that are actually occurring. The proverbial tip of the iceberg."
  • PLINQO: Advanced LINQ to SQL
    • In the time that LINQ to SQL has been available, we have been identifying ways to make LINQ to SQL better. We have compiled all of those cool tips and tricks including new features into a set of CodeSmith templates. PLINQO opens the LINQ TO SQL black box giving you the ability to control your source code while adding many new features and enhancements. It's still LINQ to SQL, but better!

Hope to see you soon!
~ Tom 

Tuesday, March 8, 2011

PLINQO for NHibernate?

As my Uncle Ben once said, "with great insomnia comes great responsibility." Or maybe that was Spiderman, I don't remember. All I know is that I couldn't go to sleep last night, and when I came to this morning there was a proof of concept PLINQO for NHibernate architecture on my screen.

I am not saying we are working on PLINQO for NHibernate...yet.

NHibernate is a well established ORM that is backed by a great community, and frankly, they have their own way of doing things. NHibernate is built on some great principals: patterns, testability, and openness. Also, things like Fluent NHibernate and Sharp Architecture are examples of some superb extensions to the base NHibernate framework, and they are perfectly tailored to fit NHibernate needs.

Originally we had thought that creating PLINQO templates for NHibernate would be going against the grain of the NHibernate community. The architecture of PLINQO, specifically it's query extension pattern, is a bit of an anti-pattern. Also PLINQO is based on LINQ to SQL, and not all of it's features are needed in the more mature NHibernate framework.

So if we were to make PLINQO for NHibernate, what value would it provide?

First and foremost, simplicity.
A major goal of PLINQO is to get the end user up and running as fast as possible. A major complaint of NHibernate is that it can be very complex to setup. It seems that simplifying the start up process would be a major advantage to new users.

This could provide a migration path to NHibernate.
Using LINQ to SQL or PLINQO and want to switch to NHibernate? Maybe you need more DB Providers, maybe you like open source components, or maybe you have converted to the church of Rhino; in any case, this would be a great way to make that transition quick and easy.

PLINQO for NHibernate means more PLINQO.
...and I LOVE PLINQO! I certainly don't think more PLINQO could hurt anyone, heck, I'm pretty sure that it will help someone! Also, on a personal note, I would get to code more PLINQO! If you can't tell from all the exclamation points, I find that prospect to be freak'n exciting!

What would PLINQO for NHibernate look like?

Remember back when you were in grade school and your teacher told you that there were no stupid questions? That was a stupid question.

Ideally the PLINQO NHibernate templates would generate you a matching data layer. You would swap out your templates, update your namespaces, and you're back in business.

[Test]
public void ByQueries()
{
    // This DataContext is powered by a NHibernate ISession
    using (var db = new PetshopDataContext())
    {
        var x = db.Product
            .ByName(ContainmentOperator.NotEquals, "A")
            .ByDescn("B")
            .FirstOrDefault();

        var y = db.Product
            .ByName(ContainmentOperator.StartsWith, "B")
            .ByDescn("B");
                
        var z = y.ToList();

        Assert.AreEqual(1, z.Count);
        Assert.AreEqual(x.Id, z[0].Id);
    }
}

So by the way, that code snippet is real, and that test succeeds.

Tuesday, March 1, 2011

Error Handling and CustomErrors and MVC3, oh my!

So, what else is new in MVC 3?
MVC 3 now has a GlobalFilterCollection that is automatically populated with a HandleErrorAttribute. This default FilterAttribute brings with it a new way of handling errors in your web applications. In short, you can now handle errors inside of the MVC pipeline. 

What does that mean?
This gives you direct programmatic control over handling your 500 errors in the same way that ASP.NET and CustomErrors give you configurable control of handling your HTTP error codes.

How does that work out?
Think of it as a routing table specifically for your Exceptions, it's pretty sweet!

Global Filters

The new Global.asax file now has a RegisterGlobalFilters method that is used to add filters to the new GlobalFilterCollection, statically located at System.Web.Mvc.GlobalFilter.Filters. By default this method adds one filter, the HandleErrorAttribute.

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

HandleErrorAttributes

The HandleErrorAttribute is pretty simple in concept: MVC has already adjusted us to using Filter attributes for our AcceptVerbs and RequiresAuthorization, now we are going to use them for (as the name implies) error handling, and we are going to do so on a (also as the name implies) global scale.

The HandleErrorAttribute has properties for ExceptionType, View, and Master. The ExceptionType allows you to specify what exception that attribute should handle. The View allows you to specify which error view (page) you want it to redirect to. Last but not least, the Master allows you to control which master page (or as Razor refers to them, Layout) you want to render with, even if that means overriding the default layout specified in the view itself.

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute
        {
            ExceptionType = typeof(DbException),
            // DbError.cshtml is a view in the Shared folder.
            View = "DbError",
            Order = 2
        });
        filters.Add(new HandleErrorAttribute());
    }

Error Views

All of your views still work like they did in the previous version of MVC (except of course that they can now use the Razor engine). However, a view that is used to render an error can not have a specified model! This is because they already have a model, and that is System.Web.Mvc.HandleErrorInfo

@model System.Web.Mvc.HandleErrorInfo
           
@{
    ViewBag.Title = "DbError";
}

<h2>A Database Error Has Occurred</h2>

@if (Model != null)
{
    <p>@Model.Exception.GetType().Name<br />
    thrown in @Model.ControllerName @Model.ActionName</p>
}

Errors Outside of the MVC Pipeline

The HandleErrorAttribute will only handle errors that happen inside of the MVC pipeline, better known as 500 errors. Errors outside of the MVC pipeline are still handled the way they have always been with ASP.NET. You turn on custom errors, specify error codes and paths to error pages, etc.

It is important to remember that these will happen for anything and everything outside of what the HandleErrorAttribute handles. Also, these will happen whenever an error is not handled with the HandleErrorAttribute from inside of the pipeline.

<system.web>
  <customErrors mode="On" defaultRedirect="~/error">
    <error statusCode="404" redirect="~/error/notfound"></error>
  </customErrors>

Sample Controllers

public class ExampleController : Controller
{
    public ActionResult Exception()
    {
        throw new ArgumentNullException();
    }
    public ActionResult Db()
    {
        // Inherits from DbException
        throw new MyDbException();
    }
}

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    public ActionResult NotFound()
    {
        return View();
    }
}

Putting It All Together

If we have all the code above included in our MVC 3 project, here is how the following scenario's will play out:

  1. A controller action throws an Exception.
    • You will remain on the current page and the global HandleErrorAttributes will render the Error view.
  2. A controller action throws any type of DbException.
    • You will remain on the current page and the global HandleErrorAttributes will render the DbError view.
  3. Go to a non-existent page.
    • You will be redirect to the Error controller's NotFound action by the CustomErrors configuration for HTTP StatusCode 404.

But don't take my word for it, download the sample project and try it yourself.

Three Important Lessons Learned

For the most part this is all pretty straight forward, but there are a few gotcha's that you should remember to watch out for:

1) Error views have models, but they must be of type HandleErrorInfo.

It is confusing at first to think that you can't control the M in an MVC page, but it's for a good reason. Errors can come from any action in any controller, and no redirect is taking place, so the view engine is just going to render an error view with the only data it has: The HandleError Info model. Do not try to set the model on your error page or pass in a different object through a controller action, it will just blow up and cause a second exception after your first exception!

2) When the HandleErrorAttribute renders a page, it does not pass through a controller or an action.

The standard web.config CustomErrors literally redirect a failed request to a new page. The HandleErrorAttribute is just rendering a view, so it is not going to pass through a controller action. But that's ok! Remember, a controller's job is to get the model for a view, but an error already has a model ready to give to the view, thus there is no need to pass through a controller.

That being said, the normal ASP.NET custom errors still need to route through controllers. So if you want to share an error page between the HandleErrorAttribute and your web.config redirects, you will need to create a controller action and route for it. But then when you render that error view from your action, you can only use the HandlerErrorInfo model or ViewData dictionary to populate your page.

3) The HandleErrorAttribute obeys if CustomErrors are on or off, but does not use their redirects.

If you turn CustomErrors off in your web.config, the HandleErrorAttributes will stop handling errors. However, that is the only configuration these two mechanisms share. The HandleErrorAttribute will not use your defaultRedirect property, or any other errors registered with customer errors.

In Summary

The HandleErrorAttribute is for displaying 500 errors that were caused by exceptions inside of the MVC pipeline. The custom errors are for redirecting from error pages caused by other HTTP codes. 

Also, if you are going to be handling all these errors, why not report them too?

Real Time Web Analytics