Microsoft Visual Studio® .NET
Java Server Pages (JSP)
Summary: Learn how to work with directives in both JSP and ASP.NET. (10 printed pages)
Directives are language-specific elements used to set or modify the structure of servlet classes (in JSP) and the settings of the parser and compiler (in Microsoft® ASP.NET). In both cases, directives are responsible for changing settings that govern the actions of an entire page.
For JSP developers who are migrating their code into ASP.NET, you will find that the format of directives in both languages is conveniently similar. In both cases, the normal set of
<% %> brackets that surrounds a JSP- or ASP.NET-specific element is replaced by
<%@ %>, the additional
@ symbol indicating that the content of this element is a directive. In both languages, as well, the name of the directive being used immediately follows the
@ symbol, although directive names differ between JSP and ASP.NET.
This article will provide an overview of the available directives in JSP and then compare them to similar directives available in ASP.NET. It is not a complete reference to every attribute of every directive, but we will provide links to references when and where they are available.
The JSP 1.2 specification defines three directives: page, which controls session state, imported packages, content type, and other page-specific settings; include, which allows you to include files in the servlet into which the JSP page will be translated; and taglib, which allows you to import custom tag libraries for use in JSP pages. Each of these directives is discussed in the following sections.
The page directive allows you to define and change properties for a JSP page. page directives contain a set of attributes (name-value pairs), each of which controls a different property. You can have as many page directives as you want in a given JSP page, but each attribute (with the exception of the import attribute) can only appear once on a page.
Listing 1 shows an example of a page directive used on the CodeNotes Web site. This particular directive is located in the JSP that contains the sub-navigation menus for the main CodeNotes page, but similar directives can be found throughout the site. The directive in Listing 1 imports an additional package (com.codenotes.web.Links), which is part of the Web site's Struts framework and has methods that are used to determine the endpoints of hyperlinks. The directive also indicates that the page has an error page (to which a user will be forwarded in the event of an unhandled error) available at the URL subnav_error.jsp.
Listing 1. Example of a page directive in JSP
<%@ page import="com.codenotes.web.Links" errorPage="subnav_error.jsp" %>
The attributes seen above, as well as some others, are described next.
The following is a list of page directive attributes with a brief description of each. A complete reference can be found in section 2.10.1 of the JSP specification.
- language indicates the language in which the scripts in the JSP page are written. The only valid value in the JSP 1.2 specification is Java, which is always assumed if the attribute isn't present.
- extends allows you to specify a class name from which the servlet class into which the JSP will be transformed is extended. This method may have some severe performance drawbacks, which are detailed in the specification.
- import allows you to import packages or classes beyond the default list of imported classes and packages for JSP pages, which includes java.lang.*, javax.servlet.*, javax.servlet.jsp.*, and javax.servlet.http.*.
- session is a Boolean attribute indicating whether or not session state is maintained for the page.
- buffer allows you to indicate a buffer size for output with values in the format XXKB where XX represents an integer amount of kilobytes to use as a buffer. The value of this attribute can also be none.
- autoFlush—when a buffer is used, this Boolean attribute indicates whether or not the buffer should be flushed automatically when it becomes full. Usually you will want this attribute set to true (the default value).
- isThreadSafe indicates whether or not the page is thread safe.
- info allows you to provide human-readable documentation for the JSP page that can be obtained programmatically (using the Servlet.getServletInfo() method).
- errorPage allows you to specify a relative URL to an error page, to which the user will be forwarded if an unhandled error occurs.
- isErrorPage indicates whether or not this JSP page is an error page.
- contentType indicates the MIME content type of the page, in the form type; charset=charset.
- pageEncoding indicates the character encoding used for the page. This value can also be defined using the contentType attribute.
The include directive allows you to directly include text or code from another file in the JSP page. When the page is parsed and compiled, the directive tag will be replaced by the content of the file at the URL provided by the directive.
We don't use the include directive on the CodeNotes site. Instead, we use a Struts tag library and add various pieces to our pages using custom tags. However, if we did use include directives instead, a typical page might look something like Listing 2.
Listing 2. Alternate anonymousHome.jsp
<%@ include file="/jsp/home/mainHeading.jsp" %> <%@ include file="/jsp/home/subnav/subnav_home.jsp" %> <%@ include file="/jsp/home/content/content_anonymousHome.jsp" %>
Each of these included JSPs would contain a different segment of the main page. When put together, they would become a complete HTML page. You would then be able to edit segments separately and reuse them in different combinations, without changes to one segment affecting another.
If you use an include directive, the content is placed into the JSP code and is actually parsed by the JSP container. There is an alternative method of including files in a JSP page that does not parse the files and instead inserts them only when the page is requested. This method is shown in Listing 3.
Listing 3. Including files in place
The taglib directive allows you to import a custom tag library into your JSP file so that the tags in that library can be used. The taglib directive specifies the location of the tag library and a prefix that will be used to identify tags from this library throughout the document. Note that the prefix and the imported tags can only appear after the taglib directive on the page.
Listing 4 shows an example of a typical taglib usage from the CodeNotes Web site. This particular example is actually the entire content of anonymousHome.jsp, which represents the main page of the Web site if a user has not logged in. In this case, we are importing a Struts template that is used to structure the page. Imports of the actual separate JSPs that make up each page on the CodeNotes Web site are hidden inside the Struts tag library, so that page construction can be accomplished by simply using a few special Struts elements (insert and put).
Listing 4. Example taglib directive
<%@ taglib uri='/WEB-INF/taglib/struts-template.tld' prefix='template' %> <template:insert template='/jsp/template/mainTemplate.jsp'> <template:put name='title' content='Home' direct='true'/> <template:put name='subnav' content='/jsp/home/subnav/subnav_home.jsp'/> <template:put name='content' content='/jsp/home/content/content_anonymousHome.jsp'/> </template:insert>
You can find more information on tag libraries in JSP in the tag libraries and Web controls article included in this migration guide.
The JCLA does a fairly straightforward conversion of JSP directives, meaning that you will rarely have to manually edit the generated ASP.NET directives to get them to work just like the originals. However, some attributes of the page directive in JSP (such as import) are placed in their own directive blocks in ASP.NET. Let's look at some examples.
Example 1: The page Directive
In Listing 1 we showed an example of a JSP page directive. For convenience, here it is again in Listing 5.
Listing 5. A JSP page directive example
<%@ page import="com.codenotes.web.Links" errorPage="subnav_error.jsp" %>
If we convert a page that contains this directive (such as subnav_home.jsp), its functionality will actually be shared between two directives in the resulting ASP.NET code. This code is shown in Listing 6.
Listing 6. ASP.NET directives
<%@ Page language="c#" ErrorPage="subnav_error.aspx" CodeBehind="subnav_home.aspx.cs" Inherits="directivesConv.subnav_home" AutoEventWireup="false"%> <%@ Import Namespace="Links=com.codenotes.web.Links"%>
The first directive, a page directive, is actually automatically added to the beginning of every ASP.NET page by the conversion engine (which can actually result in problems with some conversions, as we'll see in the next example). In this case, the part of the page directive we're interested in is the ErrorPage element, which, as you can see, points to the same error page as our original JSP. In order to get the error page functionality to work in ASP.NET, however, we need to make a change to the Web.config file for this solution.
Open Web.config and locate a section that looks like Listing 7:
Listing 7. Original <customErrors> element in converted project
<customErrors mode="RemoteOnly" />
<customErrors> element allows you to turn custom errors on and off and define error pages to which particular errors on an ASP.NET page will be directed. By default, the
<customErrors> mode is set to "RemoteOnly", which means that custom errors will only be seen by users not running on the local Web server. Since we want to be able to see our error page in action, we need to change the
<customErrors> element so that it looks like Listing 8.
Listing 8. Modified <customErrors> element
<customErrors mode="On" defaultRedirect="subnav_error.aspx" />
This will redirect all errors on the ASP.NET pages in this project to subnav_error.aspx (which is functionally identical to our error page from the original JSP application).
The other attribute in our original JSP page directive was an import attribute, used to import a reference to a class required by some of the JSP code. In ASP.NET, the import attribute has been moved into a separate directive all on its own, which resembles Listing 9.
Listing 9. Import directive
<%@ Import Namespace="Links=com.codenotes.web.Links"%>
This Import directive imports the namespace com.codenotes.web.Links (just like in the JSP), but assigns it a new, easier-to-use name: Links. The result of this is that ASP.NET code in this file can now refer to methods in the Links class simply by referencing Links.methodName().
Example 2: The Include Directive
In the first section of this article, we looked at examples of the JSP include directive, like the one in Listing 10.
Listing 10. A JSP include directive
<%@ include file="/jsp/home/mainHeading.jsp" %>
The JLCA converts this statement to an ASP.NET style import statement, with an UPGRADE_WARNING, that looks like Listing 11.
Listing 11. ASP.NET-style import statement
<%--UPGRADE_WARNING: When including files, some server-side tags that must be unique could be repeated in the page. This could cause unhandled exceptions during the page request execution. ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword="jlca2001"--%> <!--#include file="header.aspx"-->
This warning informs you that including files can result in duplication of certain tags that must be unique and, indeed, this is often the case. For example, suppose you converted a JSP application that consisted of a main page (main.jsp) and a header file (header.jsp) that was imported into the top of the main page using an include directive. The JLCA will add the same generic Page directive to the top of each newly created .aspx file. This means that when you include header.aspx into main.aspx, there will essentially be two page directives on a single ASP.NET page. This is not allowed, as page directives must be unique, and will therefore result in a parser error.
The easy solution to this problem is simply to erase the page directive from the top of header.aspx. Since this page is never going to be displayed on its own anyway, you won't need it, and the application will now work just as it did in JSP.
Keep this issue in mind if you are ever converting projects that include files, as it will almost certainly be one of the problems you will have to fix manually.
Directives in ASP.NET control the settings and properties of page and user control compilers. They can be included anywhere on a page, although it is standard to place them at the beginning. Directives are used in both .aspx files (ASP.NET pages) and .ascx files (user control pages).
ASP.NET pages actually support eight different directives. You can find a complete listing of these at .NET Framework General Reference: Directive Syntax. In this section, we will discuss the Page and Register directives, which have functionality approximately equal to the page and taglib directives in JSP.
Page directives are the most commonly used directives, and are used to edit a wide variety of settings that control how the page parser and page compiler work. If you have looked at the code of any ASP.NET pages generated under Microsoft Visual Studio® .NET, you have probably already seen an example of a Page directive used to indicate the location of the CodeBehind file for the page. Page directives can control many other aspects of the compiler, however, and we will examine the most important of these in this article.
In ASP.NET, a Page directive can appear anywhere on a page, but only one Page directive is allowed per page. This means that all settings attributes must be included in a single attribute. The default Page directive generated for every Visual Studio .NET/ASP.NET page looks something like Listing 12.
Listing 12. A sample page directive
<%@ Page language="c#" ErrorPage="subnav_error.aspx" CodeBehind="subnav_home.aspx.cs" Inherits="directivesConv.subnav_home" AutoEventWireup="false"%>
Page directives always begin with the keyword
As you can see, Page directives contain a series of attributes, each of which controls a different compiler or parser setting. In the next section, we will begin with the four attributes seen in Listing 12, and then discuss some of the other important Page directive attributes that you may want to employ in your own projects. A complete reference to all Page directive attributes can be found at .NET Framework General Reference: @ Page.
The following is a list of some of the more commonly used page directive attributes in ASP.NET.
- Language indicates the language in which the inline script code within the ASP.NET page is written (the code between
<% %>tags). The value of this attribute can be C#, VB, or JS.
- Codebehind indicates the name of the file being used as the code supporting this ASP.NET page. This file should reflect the Language setting; that is, if the language being used is C#, the CodeBehind file should have a .cs extension and be written in C#.
- AutoEventWireup is a Boolean attribute that indicates whether the ASP.NET pages events are autowired. Setting this attribute to true will cause two event methods (Page_Init and Page_Load) to be called automatically when the page is accessed. These event handlers are often generated by Visual Studio .NET when a new ASP.NET page is created. If you are using customized event handlers, these methods will not automatically be called, and your event handler methods must explicitly indicate what events they handle and when they should execute. AutoEventWireup is true by default.
- Inherits indicates a qualified class from which this ASP.NET page should inherit. Generally, this will be the name of the class described in the CodeBehind file.
- AspCompat allows you to force the page to be executed using ASP's threading mechanism (called single-threaded apartment or STA) instead of ASP.NET's mechanism (multi-threaded apartment or MTA). Setting this attribute to true will allow the page to use COM components from previous versions of Visual Studio that functioned only under STA. By default, this attribute is set to false.
- Buffer controls whether HTTP response buffering is on or off. Buffer is true by default.
- ContentType specifies a MIME type for the content of the ASP.NET page. MIME types include such strings as text/xml and text/html. A complete listing can be found at MEDIA TYPES. Note that this attribute does not actually control or validate the content type in the page; it simply informs the compiler what type is being used in case this information is needed elsewhere.
- Description contains a text description of the purpose of the ASP.NET page. This attribute is ignored by the compiler, but may be examined by other applications such as a GUI interface for a collection of ASP.NET pages.
- ErrorPage allows you to provide a URL to which the user will be redirected if an unhandled error occurs. Visual Studio .NET also allows you to provide a similar URL in the web.config file for a Web application. Either method will have the same results; you can play it safe by providing the same URL in both locations.
- SmartNavigation is a feature of Internet Explorer version 5.0 and later. This feature keeps track of where a user was on a particular page (in other words, how far down the scrollbar was) so that when the user returns to that page (by using the Back and Forward buttons) he or she is returned to the same position on the page. The SmartNavigation attribute in a page directive allows you to turn this feature on and off.
- WarningLevel controls a compiler setting that allows you to dictate how serious a warning or error must be before compilation of a page is aborted. This attribute should contain an integer value from 0 to 4. You can find information on what each setting means at .NET Framework Class Library: CompilerParameters.WarningLevel Property.
The Register directive allows you to associate a prefix with a namespace or class. Somewhat similar to the JSP taglib directive, Register makes it possible to include custom user controls or server controls that have their own tag syntax.
If you want to add a declarative user control (say you have defined a control in an .ascx file and you want to use it in your .aspx file), you can use the tagprefix, tagname, and src attributes as shown in Listing 13.
Listing 13. Adding a declarative user control
<%@ Register tagprefix=cn tagname=CodeNotes src=codenotes.ascx %>
If you have a server control that has been compiled into a .dll (or that you have downloaded as a .dll), you should use the tagprefix, namespace, and assembly combination instead. Listing 14 shows an example of this syntax, where CodeNotes.dll is the assembly file.
Listing 14. Adding a custom server control
<%@ Register tagprefix=cn namespace=Codenotes:CN-Namespace assembly=CodeNotes %>
More information on user controls is available at .NET Framework Developer's Guide: Web Forms User Controls.
More information on server controls is available at Visual Basic and Visual C# Concepts: ASP.NET Server Controls
Directives are special elements in JSP or ASP.NET pages that contain attributes used to control various properties of the page and how it is handled by an interpreter or compiler. In both JSP and ASP.NET, directives follow the form <%@ directive_name (attribute=value)* %>, although each language has different names for its directives and each directive has different attributes.
The JSP 1.2 specification defines three directives: page, import, and taglib; each of which controls certain aspects of how the page is handled. page directives allow you to control various page properties such as imported classes or packages, buffering, session state, and error page forwarding. import directives allow you to implant other text or code into your JSP page. taglib directives allow you to import custom tag libraries for use within your code. Of these, only page directives have the special rule that no attribute (with the exception of the import attribute) can appear more than once in a particular page.
Fortunately, the JLCA converts directives almost literally and you should have very few problems working with directives converted from JSP to ASP.NET.
ASP.NET directives are used to supply parameters to the ASP.NET parser and compiler. ASP.NET offers eight different directives, of which two (Page and Register) are similar to the JSP directives mentioned in this article (page and taglib, respectively). A Page directive can appear anywhere on an ASP.NET page, but only one can exist on a given page. Register directives allow you to associate prefixes with a custom namespace or class so that controls defined within it can be used in your ASP.NET pages. A complete list of ASP.NET directives and their functions can be found in the .NET Framework General Reference: @ Page.