Minggu, 23 Januari 2011
Feed has moved
RIA Services and Authentication
Authentication is the third in a series of posts covering the key concepts of RIA Services using the Book Club application to digger deeper and go beyond the basics. Links to the first two posts on validation and authorization as well as an overview of the application/source code are at the end of this post.
Authentication Overview
Like authorization, RIA Services provides a higher level programming model, and out-of-the-box, but extensible solution. Authentication answers the question:
"Do these credentials represent a valid user?"
Credentials might be user name and password, or any other piece of data that can be used to verify that the user is who he/she says they are. Generally, a side-effect of authentication is to produce a representation of the user, usually represented as an IPrincipal, as well as establishing an authenticated session for the client to use in making subsequent requests.
RIA Service defines an authentication service as a domain service that implements IAuthetication<TUser> where TUser is application's notion of a user that brings together identity, roles and settings that span across client and server.
RIA Services also provides an out-of-box implementation based on the standard asp.net membership, roles and profile infrastructure services. If you use the business application template, this is all setup for you by default. However RIA Services also lets you implement your own authentication service when you want to use your own custom credential store, or a different authentication mechanism such as OpenID.
This post covers using authentication and the User object on client and server, as well as building a custom forms authentication service that works against the application's data model.
Using Authentication on the Client
I created an inplace-LoginControl with a number of visual states (Unauthenticated, CredentialInput, Authenticating and Authenticated) as shown here.
Authentication functionality is accessed through a class called WebContext on the client. WebContext represents the functionality provided by the home web server to the client application. This is how WebContext is initialized in the application:
[Full post continued here...]
RIA Services and Authentication - Part 2 (Using Roles)
When I posted my RIA Services and Authentication post earlier in the week (which I highly recommend checking out first if you haven't), the first comments/tweets I saw indicated people also want to see roles working in the application. So I decided to add this bit of functionality, both in the Book Club application and the supporting functionality in the RIAEssentials framework, so you can use it easily in your own applications as well.
From a scenario perspective, what I am going to do is require an Admin role to browse and add book club members.
Adding and Using Roles
The first step is to update the AuthenticationService implementation I showed earlier to add roles into the authentication process. It only requires quite literally a couple of minor tweaks, th. The added lines are shown in bold:
[Full post continued here...]
Config-free IHttpModule Registration
The ASP.NET pipeline allows HTTP modules to plug in into the request processing lifecycle and do work at various stages. For example, output caching, authentication, authorization etc. are all implemented as HTTP modules.
However one of the problems is that HTTP modules must be registered in configuration. This is a little painful for writing framework components where an HTTP module is essentially an implementation detail. You don't want every app developer using your framework to have to add in some configuration entries. What you want is the ability to programmatically add HTTP modules to the pipeline. This isn't available out-of-the-box today.
I faced this problem in my previous post around RIA Services, Authentication and Roles, as I needed to handle the PostAuthenticateRequest event. This seems to have come up before (for example here and here on stack overflow).
So in the interim, we can use the new, and somewhat obscure, ASP.NET 4.0 feature, the PreApplicationStartMethodAttribute, that lets you declare some code you want to run early in the initialization phase of your web application, even before any dynamic compilation happens and before any application startup code runs. Combine that capability with an HttpApplication that supports registering HTTP modules programmatically, as we're in business. I wrote DynamicHttpApplication that provides this API (link to code below):
public abstract class DynamicHttpApplication : HttpApplication {
public static void RegisterModule(Func<HttpApplication, IHttpModule> moduleFactory);
}
[Full post continued here...]
Thoughts on WebMatrix
The WebMatrix announcement last week triggered a range of reactions on Twitter. It also brought back some personal memories.
A decade ago (wow), I started a little tool to simplify using and developing asp.net server controls as a side project, and it grew bigger and was eventually released using the name "WebMatrix". It was a fun project, and my first "serious" side project so to speak. There were a few interesting things we did there, both technical and non-technical. It is great seeing similar things happening in this generation of WebMatrix branded tooling. :-)
Vertical and Scenario-Focused Tooling
I personally think having a variety of tools is good, especially if they can focus on different verticals, and are optimized for different scenarios/tasks. There is a saying - use the right tool for the job. And the reality is there is a wide spectrum of developers and correspondingly a breadth of requirements and expectations. Lots of professional/enterprise developers will find Visual Studio and its rich set of features + ecosystem a must-have for their work. At the same time, there is a huge number of Web developers, designers and scripters that primarily use Notepad, Textmate or a simple text editor to quickly build and manage their web sites and applications. For those folks, the simplicity that comes from the minimal set of options is a feature in itself. WebMatrix caters to that huge audience. This is true today, and was true back then.
[Full post continued here...]
Update on ASP.NET MVC 3 RC2 (and a workaround for a bug in it)
Last week we published the RC2 build of ASP.NET MVC 3. I blogged a bunch of details about it here.
One of the reasons we publish release candidates is to help find those last “hard to find” bugs. So far we haven’t seen many issues reported with the RC2 release (which is good) - although we have seen a few reports of a metadata caching bug that manifests itself in at least two scenarios:
- Nullable parameters in action methods have problems: When you have a controller action method with a nullable parameter (like int? – or a complex type that has a nullable sub-property), the nullable parameter might always end up being null - even when the request contains a valid value for the parameter.
- [AllowHtml] doesn’t allow HTML in model binding: When you decorate a model property with an [AllowHtml] attribute (to turn off HTML injection protection), the model binding still fails when HTML content is posted to it.
Both of these issues are caused by an over-eager caching optimization we introduced very late in the RC2 milestone. This issue will be fixed for the final ASP.NET MVC 3 release. Below is a workaround step you can implement to fix it today.
Workaround You Can Use Today
You can fix the above issues with the current ASP.NT MVC 3 RC2 release by adding one line of code to the Application_Start() event handler within the Global.asax class of your application:
The above code sets the ModelMetaDataProviders.Current property to use the DataAnnotationsModelMetadataProvider. This causes ASP.NET MVC 3 to use a meta-data provider implementation that doesn’t have the more aggressive caching logic we introduced late in the RC2 release, and prevents the caching issues that cause the above issues to occur.
You don’t need to change any other code within your application. Once you make this change the above issues are fixed. You won’t need to have this line of code within your applications once the final ASP.NET MVC 3 release ships (although keeping it in also won’t cause any problems).
Hope this helps – and please keep any reports of issues coming our way,
Scott
P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu
ASP.NET MVC 3: Razor’s @: and syntax
This is another in a series of posts I’m doing that cover some of the new ASP.NET MVC 3 features:
- New @model keyword in Razor (Oct 19th)
- Layouts with Razor (Oct 22nd)
- Server-Side Comments with Razor (Nov 12th)
- Razor’s @: and <text> syntax (today)
In today’s post I’m going to discuss two useful syntactical features of the new Razor view-engine – the @: and <text> syntax support.
Fluid Coding with Razor
ASP.NET MVC 3 ships with a new view-engine option called “Razor” (in addition to the existing .aspx view engine). You can learn more about Razor, why we are introducing it, and the syntax it supports from my Introducing Razor blog post.
Razor minimizes the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow. Unlike most template syntaxes, you do not need to interrupt your coding to explicitly denote the start and end of server blocks within your HTML. The Razor parser is smart enough to infer this from your code. This enables a compact and expressive syntax which is clean, fast and fun to type.
For example, the Razor snippet below can be used to iterate a list of products:
When run, it generates output like:
One of the techniques that Razor uses to implicitly identify when a code block ends is to look for tag/element content to denote the beginning of a content region. For example, in the code snippet above Razor automatically treated the inner <li></li> block within our foreach loop as an HTML content block because it saw the opening <li> tag sequence and knew that it couldn’t be valid C#.
This particular technique – using tags to identify content blocks within code – is one of the key ingredients that makes Razor so clean and productive with scenarios involving HTML creation.
Using @: to explicitly indicate the start of content
Not all content container blocks start with a tag element tag, though, and there are scenarios where the Razor parser can’t implicitly detect a content block.
Razor addresses this by enabling you to explicitly indicate the beginning of a line of content by using the @: character sequence within a code block. The @: sequence indicates that the line of content that follows should be treated as a content block:
As a more practical example, the below snippet demonstrates how we could output a “(Out of Stock!)” message next to our product name if the product is out of stock:
Because I am not wrapping the (Out of Stock!) message in an HTML tag element, Razor can’t implicitly determine that the content within the @if block is the start of a content block. We are using the @: character sequence to explicitly indicate that this line within our code block should be treated as content.
Using Code Nuggets within @: content blocks
In addition to outputting static content, you can also have code nuggets embedded within a content block that is initiated using a @: character sequence.
For example, we have two @: sequences in the code snippet below:
Notice how within the second @: sequence we are emitting the number of units left within the content block (e.g. - “(Only 3 left!”). We are doing this by embedding a @p.UnitsInStock code nugget within the line of content.
Multiple Lines of Content
Razor makes it easy to have multiple lines of content wrapped in an HTML element. For example, below the inner content of our @if container is wrapped in an HTML <p> element – which will cause Razor to treat it as content:
For scenarios where the multiple lines of content are not wrapped by an outer HTML element, you can use multiple @: sequences:
Alternatively, Razor also allows you to use a <text> element to explicitly identify content:
The <text> tag is an element that is treated specially by Razor. It causes Razor to interpret the inner contents of the <text> block as content, and to not render the containing <text> tag element (meaning only the inner contents of the <text> element will be rendered – the tag itself will not). This makes it convenient when you want to render multi-line content blocks that are not wrapped by an HTML element.
The <text> element can also optionally be used to denote single-lines of content, if you prefer it to the more concise @: sequence:
The above code will render the same output as the @: version we looked at earlier. Razor will automatically omit the <text> wrapping element from the output and just render the content within it.
Summary
Razor enables a clean and concise templating syntax that enables a very fluid coding workflow. Razor’s smart detection of <tag> elements to identify the beginning of content regions is one of the reasons that the Razor approach works so well with HTML generation scenarios, and it enables you to avoid having to explicitly mark the beginning/ending of content regions in about 95% of if/else and foreach scenarios.
Razor’s @: and <text> syntax can then be used for scenarios where you want to avoid using an HTML element within a code container block, and need to more explicitly denote a content region.
Hope this helps,
Scott
P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu