Wednesday, June 27, 2007

What IS a closure?

"Anonymous methods are not closures," is the refrain I've heard when I tell people that .NET supports closures.

Ian Griffiths thinks otherwise, and I agree.

If you don't believe me, go read up on it for your self.

A more apropos question would be--what are closures useful for in day-to-day programming?

Here's one guys attempt to answer that question, at least for the Ruby programmer. I've taken his example and turned it into C#. You really have to get to the point where closure are as accessible to you as a for loop or an if statement before you have the epiphany that make the question above seem droll.


delegate void LogDelegate(string message);
void DoSomething()
{
LogDelegate logger;
SerialNumber serialNumber = NextSerialAndLog(out logger);

logger("process 1");
logger("process 2");
logger("process 3");
}

SerialNumber NextSerialAndLog(out LogDelegate l)
{
sn = new SerialNumber();
l = delegate(string message)
{
LogInfo("DoSomething", sn, message);
};
return sn;
}

Tuesday, June 26, 2007

TODO: HTML Parser

Requirement: A continuation-based robust HTML parser that doesn't choke on all the crappy web documents out there. It would allow me to specify a qualifying filter to its generator method and iterate over qualifying nodes. The filter would be similar to an XPath expression, if not equivalent.

References:
Parsing HTML in Microsoft C#

Continuations for Curmudgeons (SAX section)

Dual (or Mixed) Mode Authentication with ASP.NET

On my current project, I was faced with the requirement to allow user logged-in on a the same domain as the server where the web application would run to use Integrated authentication, while at the same time supporting forms-based logins for users who did not have domain accounts. Users will always be directed to the same landing page when they are properly logged in.

I'm not going to explain why this work, or how it works, just what I did. I believe this solution is the simplest one you'll find if your requirements are the same as the above. This is not a general solution by any means, given the assumptions I am making.

Here's the basic idea. You're application will be configured to use Forms-based Authentication. You'll implement some strategy for determining if the request is coming from a domain user, if so you'll redirect them to a page that leverages Integrated authentication in IIS, otherwise they'll just do a normal form-based login. The Integrated authentication page will simply issue a Forms-based authentication ticket (via the ASP.NET FormsAuthentication API) and redirect the user to the landing page. Once you have an authenticated user, in either scenario, you will map that user to a logical (business-layer) User object in your application.

Essentially, you need to decouple your authentication mechanism from the logical user that you track in your application. Note that this does not preclue you from using the default Profile provider, since you are still issuing a Forms Auth ticket.

Here's what I did, specifically.

  1. Configure the web.config to use Forms-based authentication.
  2. Create a sub-folder called "Auth" and configure a web.config there to allow anonymous access to all files in that directory. This is crucial.
  3. Create two pages in the Auth directory: WebLogin.aspx and WinLogin.aspx.
  4. Configure the root web.config to use "~/Auth/WebLogin.aspx" for the forms authentication url.
  5. Build WebLogin.aspx as a normal forms authentication page, but add code to the Load event handler to check the IP address of the incoming request. If it is a domain user, redirect them to the WinLogin.aspx.
  6. In IIS, disable anonymous authentication and enable Integrated Windows authentication for the WinLogin.aspx page.
  7. In the Load event handler for the WinLogin.aspx, create a Forms Auth ticket for the logged in user.
That's the basic idea. You can use the Profile object for some light personalization, but if you need to do any auditing or authorization, you'll want to have a logical user object that you construct using either a Guid (Forms authentication) or a SID (Windows authentication).

At some point I will update the blog with a detailed implementation guide. For now, I hope this sets someone on the right track. For me, the conceptual block-buster was realizing I could make a proactive choice about how to authenticate the user, using their IP address.

Monday, June 25, 2007

Workflow Foundation ARCast

I used to be a podcast junkie, but I've been listening to more books lately. Besides .NET Rocks! I've been listening to ARCast for a long time. Well, as I'm trying to catch up on the interesting episodes, I ran across one on Workflow Foundation. Seeing as I am currently reading a book on WF, this seemed like good background noise while I work today.

The reason I'm blogging about it is that one of architects on the WF team that are on the podcast made a high-level statement about what WF can do for applications. I really liked his points, since they are easy to miss when you are studying the plumbing and theory of WF.

So, here they are:

  1. Ability to model your process such that it can react to change.
  2. Ability to model long-running processes.
  3. Ability to track processes and provide visibility into their state.
One could easily drill-down into each of those points, pointing out why the capabilities are important, how WF supports them, and how you can leverage them in your applications. In fact, I may do that in a series of posts over the next couple of days.

Saturday, June 23, 2007

Episodic Computation

Or, How I Learned to Stop Returning and Embrace Yield!

You really should stop reading this and go read this.

To this point in my career, I've found that Addison Wesley can be counted upon to deliver the more academically-minded texts on the topics I'm interested. "Essential Windows Workflow Foundation" is no exception. I am so very happy that I took this book seriously and began studying it with an eye toward a deeper understanding than just solving the problem in front of me.

I am, however, consistently struck by my own naivete when it comes to what can only be considered foundation computer science concepts. For example, I don't think I would have been fully able to articulate the differences and purposes of Subroutines, Coroutines, Continuations, Closures, and Generators. So, after an hour with Wikipedia, I am attempting share what I've learned--more for my benefit than yours. Seek first to understand, then to be understood.

Subroutines are special cases of Coroutines. Coroutines can be implemented with Continuations, while Continuations are just bookmarks for Closures. And, Generators can be thought of as a special case of a Coroutine that returns a value when it yields.

Confused? Good, that means you'll read the rest.

So, a Subroutine is (if you're a C# or VB developer) just a function.

A Coroutine is a Subroutine that can pause its execution and resume it when control flow is given back to it.

A more correct way to say it is that a Subroutine is just a Coroutine that returns only once, i.e. it always starts with a clean slate--it never resumes.

In order to resume a Coroutine, you have to keep track of where the Coroutine left off and the current state of its values (its stack frame). Bottling all that up into a kind of primitive, we call it a Continuation. So, if your language allows us to store the stack frame and an execution pointer (the last instruction), you have Continuations. If you have Continuations, you can write Coroutines. C# does this with the yield statement, which is just a fancy compiler trick for creating a state machine around the current point of execution.

A Continuation, then, requires two things to be of use: a stored re-entry point (a bookmark) and a saved variable state for a function. The later is what is known as a Closure. Specifically, a Closure looks around in its current lexical context (the written code where names (of variables) can be resolved) and packages up all that stuff into its definition, as needed. So, a Continuation can use a Closure to pick up where it left off.

Closures have a lot more general usage than just as a crutch for Continuations, but I'll leave that digression as an exercise for the reader.

Finally, Generators are just Continuations, but they return a value. To my understanding, Generators are just iterators, though one might think of a Generator as an iterator for an infinite series (think Fibonacci numbers, digits of pi, etc.); the salient difference being wether the client has to stop the iteration/generation or if the Continuation will eventually stop resuming.

What does all of this have to do with Episodic Computation or Workflow Foundation (WF)? Well, one can think of WF as an attempt to extend these and related concepts to the application level, as an attempt to create resumable programs, as an enabler of "episodic" computation. Essentially, WF wraps your higher-level imperative concepts (e.g. GenerateBillOfLading, CheckProductInventory) in "Coroutines" that can execute across processes. In other words, it is a framework for programming at the logical level.

That last statement is the Gestalt of WF. Unfortunately, that kind of expressiveness comes at a price: about USD$33

Friday, June 22, 2007

Silverlight Done Light

I recently attended a .NET user's group meeting in my area on the subject of Silverlight. I had been to a couple of these meetings before and had been generally disappointed with the quality of the presentations. The Silverlight presentation was no exception.

Don’t get me wrong; I’m really excited about Silverlight. The talk, however, met with the quality expectations I’ve been obliged to adopt with free talks. You just can’t get at any sort of depth in an hour with a naïve audience. And people tend not to prepare as well for a talk that they are giving for free.

In any event, I did find a whole bunch of stuff about Silverlight on Channel 9 over the weekend. Specifically, check out the Guthrie video and the screencasts.

  • Silverlight is a 4MB plug-in due out near the end of the year that runs on IE/FF/Safari.
  • Silverlight is a separate run-time that reuses much of what is in the .NET 3.5 runtime. The approximately 20MB .NET redistributable was shrunk to 4MB by cutting platform-specific functionality and ruthlessly removing “convenience” code (e.g. Windows Service control classes and Color.Fuscia, respectively).
  • Since .NET 2.0, Microsoft has been implementing a “platform abstraction layer” that plays a key role in providing a uniform runtime that “just works” on the Mac.
  • Silverlight includes broad support for video playback, including VC-1 (high-def).
  • Silverlight works on mobile devices.
  • Because Silverlight is effectively a subset of .NET, one can use any .NET language to write Silverlight applications. These include, but are not strictly limited to: C#, VB.NET, Python, Ruby, and C++.
  • The Silverlight tools for making creative assets are a new suite of tools called the Expression Studio: including Expression Design (vector and raster graphic asset creation: think Illustrator/Flash), Expression Web (think DreamWeaver/FrontPage), Expression Media (personal desktop organizer for media assets as well as encoding support), and Expression Blend (formerly known as Sparkle and Expression Interactive Designer). Expression Blend works natively with Visual Studio projects and is positioned as the tool for the designer on a development team. Read more at: http://www.microsoft.com/expression/
You can check out some real Silverlight applications here.

Selected Event not Firing for SqlDataSource: CancelSelectOnNullParameter

The problems I've had with declarative code are the subject of another post, but suffice it to say that I have not yet achieved "declarative enlightenment." Nevertheless, I dutifully trudge forward, using the SqlDataSource object instead of explicitly grabbing my data.


The main idea behind declarative programming is to make programmer intent more easily expressible and creating a SqlDataSource and telling a control the ID of that data source is right in-line with that idea. Unfortunately, things break down when the code running behind the declarative markup makes assumptions about your intent that are non-intuitive.


Enter the Boolean CancelSelectOnNullParameter of the SqlDataSource. This very well-named property defaults to TRUE. That's right, if you have multiple parameters on your SelectCommand and one of them is null, the SqlDataSource will not execute the SelectCommand. The page will blithely continue executing and the control(s) that are bound to the SqlDataSource will not get populated.

Interestingly, the Selecting event of the SqlDataSource will fire but the Selected event will not. This makes perfect sense: what doesn't make sense is the default. Cancelling the SelectCommand is an optimization--APIs should NEVER make an assumption around an optimization.

Using SqlCacheDependency with SQL Server 2005 in ASP.NET 2.0

Some time ago I spent an afternoon hunting around the web for the details on how the SqlCacheDependency in ASP.NET 2.0 works with SQL Server 2005. It turns out that the class performs an automatic configuration of a SQL Server 2005 query notification. Not sure what that is?Using and Monitoring Sql Query Notifications This is a truly excellent article to get started.



I've included the relevant links to SQL Books Online and quoted particularly relevant passages in italics. I certainly don't intend this post to be a "how-to", but I hope it helps the reader to get her arms around how to use the SqlCacheDependency and query notifications (by extension).



First, we only need to enable the service broker. Notification services is not utilized, surprisingly.



Using Query Notifications



The Database Engine uses Service Broker to deliver notification messages. Therefore, Service Broker must be active in the database where the application requests the subscription. The query notification functionality does not require or use Notification Services. Query notifications are independent of event notifications.



Secondly, we cannot use query notifications for just any type of query. There are a lot of rules on how the query is constructed that my restrict what data you can cache with the SqlCacheDependency.



Creating a Query for Notification



The query notifications functionality builds on the change detection mechanisms that the Database Engine uses to maintain indexed views. The requirements and restrictions for statements in a query for notification are similar to the requirements and restrictions for an indexed view.



It seems the overhead associated with these query notifications is mainly on updates. I'm guessing that SQL Server uses a mechanism similar to its query plan caching/reuse mechanism to identify similar queries in subscriptions.



Planning for Notifications



When query notifications are active on a table, updates to the table are more expensive. The Database Engine performs extra work to check subscriptions and, if necessary, generate notifications. Reusing internal templates helps to minimize the overhead per subscription. Therefore, you should use query notifications only for applications that submit queries with a similar structure. An application that submits queries with different structures should not use query notifications.



In addition to having normal execute and select permissions, the application user needs to have a couple of other permissions. Although granting DDL rights to the application seems deeply wrong to me, there is a wonderful article on granting minimum rights to the application.You can read more about them here.



GRANT SUBSCRIBE QUERY NOTIFICATIONS TO <database_principal>



GRANT RECEIVE ON QueryNotificationErrorsQueue TO <database_principal>



Because the SqlDependency object in the ASP.NET runtime auto-magically creates the Service Broker service, queue, and notification procedure, the application user also needs the following rights.



GRANT CREATE PROCEDURE TO <database_principal>



GRANT CREATE QUEUE TO <database_principal>



GRANT CREATE SERVICE TO <database_principal>



Actually, the class in the ASP.NET runtime that actually sets all this up is called the SqlConnectionContainer. It's quite the sophisticated class, doing all of the heavy-lifting. From what I gather, it creates procedures (named SqlQueryNotificationStoredProcedure-* where * is a GUID) that drop the service and queue when the conversation timer expires. I'm a little fuzzy on the low-level implementation, but I wanted to know why it needed these rights. So, I used Lutz Roeder's .NET Reflector to take a peek at what is going on inside the class.



The SQL Books online mentions that the user that attaches a query notification request to a command must have the following:



GRANT SEND ON SERVICE:://theservice to <database_principal>



However, the service doesn't exist until the SqlConnectionContainer creates it, so the SqlConnectionContainer grants the SEND ON SERVICE to a specific role: sql_dependency_subscriber. This role does not exist and must be created if you need to lock-down permissions as in the article above.