ASP.NET Futures (July 2007): Introduction to Dynamic Languages for ASP.NET
In the ASP.NET Futures release, the ASP.NET Dynamic Language Runtime (DLR) provides
a layer for integrating dynamic languages with the common language runtime. This
documentation covers:
- ASP.NET features supported by dynamic languages.
- How code is handled in dynamic-language pages.
With Microsoft IronPython and Managed JScript for ASP.NET, developers can use popular
dynamic languages for the .NET Framework to create compelling Web applications.
IronPython and Managed JScript for ASP.NET are free extensions to ASP.NET that are
targeted at:
- ASP.NET developers who want to enjoy the simplicity and flexibility of a dynamic
language.
- Python developers looking to harness the power of ASP.NET and its rapid application
development (RAD) environment.
Python’s clean object-oriented design, dynamic nature, richness of expression, ease
of use, and concise syntax has won over many users in the last several years. IronPython
is an implementation of the Python programming language running on the .NET Framework. It is well
integrated with the rest of the .NET Framework and makes all .NET libraries easily
available to Python programmers, while maintaining full compatibility with the Python
language. To learn more about IronPython and to download the complete source code,
please visit www.codeplex.com/ironpython.
Managed JScript is a preliminary implementation of JScript (the Microsoft implementation
of ECMAScript) as a dynamic language. Implementations of Ruby and Visual Basic are
under development. Future releases will expose hosting interfaces and the API for
integrating other languages.
Note Managed JScript is a separate language implementation from
JScript.NET. JScript.NET is a version of JScript for managed code, but it is not
a true dynamic language.
In the ASP.NET Futures (May 2007) release, support for dynamic languages in ASP.NET
was expanded from the earlier support for IronPython for ASP.NET. Support for dynamic languages
in ASP.NET is built on the Dynamic Language Runtime (DLR), a new platform currently
under development at Microsoft. The DLR simplifies hosting dynamic languages on
the common language runtime.
The addition of support for a wide variety of dynamic languages gives ASP.NET users
a new set of tools and new flexibility for building Web applications. The following
walkthroughs in this section illustrate some of the functionality of dynamic languages
in ASP.NET.
In addition, dynamic languages work well with dynamic data controls for ASP.NET,
a set of server controls that simplify the creation of data-driven Web applications.
For more information, see Introduction
to Dynamic Data Controls for ASP.NET and
Walkthrough: Using Dynamic Data Controls with ASP.NET.
ASP.NET Features Supported by Dynamic Languages
If you already develop .NET pages, using dynamic language pages will not require
a great deal of new learning. Most standard ASP.NET features are supported, including
the following:
- Pages (.aspx files), user controls (.ascx files), and master pages (.master files).
- Server controls; that is, elements with the
runat="server" attribute.
- Code that is included either inline or in separate code files. There are some differences
from the standard ASP.NET compilation model, which are discussed later.
- Code snippets; that is,
<% ... %>, <%= ... %>, and
<%# ... %>.
Application File
Dynamic languages for ASP.NET support a file similar to the Global.asax file. The
file is named Global.ext, where ext is the language-specific extension.
For example, the extension for IronPython files is .py, so the file name is Global.py.
Unlike the Global.asax file, which contains a directive (<%@ %>
element) and a script block with a runat="server" attribute, the Global.ext
file contains only code. For example, a simple global application file might contain
code like the following:
def Application_BeginRequest(app):
app.Response.Write('Hello application!')
IronPython
App_Script Directory
A dynamic language application contains an App_Script folder that is similar to
the App_Code directory, except that it contains dynamic-language script files instead
of static language code files. The purpose is the same, however; files in this directory
contain classes that can be used by code anywhere in the application.
Generic HTTP Handlers
A dynamic language application can contain an HTTP handler that is the equivalent
of an .ashx file in a standard ASP.NET application, although there are some differences.
Dynamic language handlers are implemented as .aspx files. As with the Global.ext
file, handlers in dynamic language applications contain only code. For example,
a simple dynamic language handler named HelloWorldHandler.aspx might contain the
following:
<%@ Page Language="IronPython" %>
<Script runat="server">
Response.ContentType = "text/plain"
Response.Write("Hello World")
</Script>
IronPython
HTTP Handler Example in IronPython
HTTP Handler Example in Managed JScript
Features Not Supported
The dynamic languages for ASP.NET feature do not currently support an equivalent
of Web services (.asmx files). The Web service architecture works only with standard
.NET Framework types, which can be difficult to create with dynamic languages. In
addition, Web service class methods must be decorated with special metadata attributes
such as WebMethodAttribute, and many dynamic languages have no syntax
for applying attributes.
In the .NET Framework version 2.0, dynamic languages require full trust to emit
Microsoft intermediate language (MSIL) for compilation at run time.
How Code Is Handled in Dynamic Language Pages
One difference between managed code and dynamic languages is the compilation model.
Dynamic languages do not use CodeDOM, the core of the code-generation model for
standard ASP.NET pages. The standard code-handling model requires inheriting from
a base class and overriding members with specific type signatures. This can be problematic
for dynamic languages.
In contrast to the standard compilation model, in which all user code in a page
becomes part of a generated source file, each piece of dynamic language code in
a page is treated as an individual entity. The implications of this are best seen
by considering the various types of user code.
Code in <script> Elements
In standard ASP.NET pages, all user code in <script> elements
that have the runat="server" attribute becomes part of the generated
class. In contrast, in dynamic language pages, no new class is generated. Instead,
ASP.NET directly instantiates the class specified by the inherits attribute.
In this respect, the term "inherits" is inaccurate for dynamic language pages, because
no inheritance occurs.
Instead of becoming part of a class, the code in a <script> element
becomes a kind of companion code for the ScriptPage class. For example,
the Page_Load method shown in the following example is not part of
any class.
<script runat="server">
def Page_Load(sender, args):
Response.Write("<p>Page_Load!</p>")
</script>
IronPython
Instead, members of the ScriptPage class, such as Response
in this example, are injected by ASP.NET so that they are directly available to
your code. The effect is that the members appear to be part of the class.
In dynamic language terminology, the code in the script block lives in a module.
Usually there is one module associated with each HTTP request.
Code-behind Files
Everything that applies to code in <script> elements applies
also to code in separate files. In the standard model, the code file contains a
partial class declaration, which the compiler merges with the generated class. With
dynamic languages, however, there is no class declaration in the code file. Instead,
methods appear directly in the file, outside of any containing construct. Therefore,
as with normal ASP.NET pages, the question of where to put your dynamic language
code is purely a matter of personal preference
Code Snippets
Snippet expressions and statements (that is, <%= ... %> and
<% ... %>) also execute in the context of the module created for
the code belonging to the page. As a result, these snippets have access to methods
and variables defined inline, in <script> elements, or in separate
code files. For example, if you define a Multiply method in a <script>
block, you can write <%= Multiply(6,7) %> in your page.
Code snippets also have access to the members of the Page class. For
example, you can write <%= Title %> to display the title
of the page.
Data-Binding Expressions
Data-binding expressions are a type of code snippet, but they are worth discussing
separately because they work more naturally with dynamic languages.
In standard ASP.NET code, you might have a GridView control with a
templated column containing the data-binding expression <%# Eval("City") %>.
The Eval method is used to get the value the column named City
for the current row in the data source.
With dynamic languages, the snippet is simply <%# City %>.
City is a code expression in the dynamic language instead of a literal
string that must be interpreted by using the Eval method. This means
you can write expressions containing arbitrary code. For example, with IronPython
you can write <%# City.lower() %> to display the value of the
column in lower case.
This straightforward and powerful syntax is possible because dynamic languages support
late-bound evaluation. The meaning of City is not known at parse time,
but the dynamic language engine is able to bind it to the correct object at run
time.
Dynamic Injector Mechanism
The compilation model for dynamic languages enables you to use simple syntax into
which additional code is injected at run time. For example, you might have code
that reads a value from the query string. The URL for the page might look like this:
http://someserver/somepage.aspx?MyValue=17
In a C# page, you can use the following code to obtain the value:
String myValue = Request.QueryString["MyValue"];
The dynamic injector mechanism allows you to write much simpler code in dynamic
languages, as shown in the following examples:
IronPython
The support code for dynamic languages enables the registration of an object referred
to as an injector. By registering as an injector, the object agrees to handle
code that matches a certain pattern. For example, if the dynamic language engine
is unable to resolve the expression SomeObj.SomeName, where SomeObj
is an HttpRequest object and SomeName is not a real property
of the HttpRequest object, the engine calls the injector that has been
registered to handle that pattern. The injector handles the expression by calling
SomeObj.QueryString["SomeString"]. The net effect is exactly the same,
but the syntax is much cleaner.
The injector mechanism has many potential uses. For example, wherever you would
write SomeControl.FindControl("SomeChildControl") in C#, you can write
SomeControl.SomeChildControl in a dynamic language application. The
mechanism is extensible and can be applied to any collection that is indexed by
strings.
Compilation of Dynamic Code
Dynamic language engines parse code at run time, compile it on the fly, and execute
the compiled code. They are not interpreters. Compiled code is reused wherever possible,
for better performance.
See Also
The New Dynamic Language
Extensibility Model for ASP.NET (Word
version, .pdf version)
|