1. Trang chủ
  2. » Công Nghệ Thông Tin

ASP.NET 4 Unleased - p 150 pdf

10 187 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 545,05 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The web configuration file in Listing 31.11 includes an section that registers the LookupExpressionBuilder class for the prefix lookup.. When you use an ExpressionBuilder in a normal AS

Trang 1

// Add Select with conString overload

AddSelectConString(dataType, xmlData);

// Create namespace

CodeNamespace dataNS = new CodeNamespace(“Data”);

// Add class to namespace

dataNS.Types.Add(dataType);

// Create code unit

CodeCompileUnit dataCode = new CodeCompileUnit();

// Add namespace to code unit

dataCode.Namespaces.Add(dataNS);

// Add default namespaces

dataNS.Imports.Add(new CodeNamespaceImport(“System”));

return dataCode;

}

}

}

The DataBuildProvider’s GenerateCode() method loads a data file into an XmlDocument

The VirtualPath property represents the path of the file being built For example, if you

add a file named Products.data to your project, the VirtualPath property would

repre-sent the path to the Products.data file

Next, the code for the data access component is created from the XML file by the

GetDataCode() method, which makes heavy use of the CodeDom to generate the code in a

language-neutral manner Working with the CodeDom is a strange and tedious experience

You must build up a block of code by building a code tree In Listing 31.9, a

CodeCompileUnit named dataCode is created A CodeNamespace named dataNS that

represents a namespace is created and added to the CodeCompileUnit And a

CodeTypeDeclaration named datatype that represents a class is added to the namespace

After the class is created, the methods and properties are added to the class block by block

An ExpressionBuilder class generates one expression from another expression Typically,

you use an ExpressionBuilder to look up a particular value given a particular key

The ASP.NET Framework includes the following ExpressionBuilder classes:

AppSettingsExpressionBuilder—Retrieves values from the appSettings section of

the web configuration file

Trang 2

ConnectionStringsExpressionBuilder—Retrieves values from the

connectionStrings section of the web configuration file

ResourceExpressionBuilder—Retrieves values from resource files.

The ConnectionStringsExpressionBuilder has been used throughout this book whenever

a connection string has needed to be retrieved

You use the following syntax when working with an ExpressionBuilder:

<%$ ConnectionStrings:MyDatabase %>

The <%$ and %> tags mark an expression that should be parsed by an ExpressionBuilder

The prefix ConnectionStrings is mapped to the particular ExpressionBuilder class

responsible for parsing the expression ExpressionBuilders must always be used with

control properties For example, you cannot display a connection string in a page like this:

<%$ ConnectionStrings:MyDatabase %>

Instead, you must display the connection string like this:

<asp:Literal

Id=”ltlConnectionString”

Text=’<%$ ConnectionStrings:MyDatabase %>’

Runat=”server” />

You can create a custom ExpressionBuilder when none of the existing

ExpressionBuilder classes do what you need For example, you might want to store your

application settings in a custom section of the web configuration file In that case, you

might want to create a custom ExpressionBuilder that grabs values from the custom

configuration section

Creating a Lookup ExpressionBuilder

In this section, you learn how to extend ASP.NET Framework by building a custom

ExpressionBuilder class We create a Lookup ExpressionBuilder that looks up string

values from an XML file

The LookupExpressionBuilder class is contained in Listing 31.10

LISTING 31.10 App_Code\LookupExpressionBuilder.cs

using System;

using System.CodeDom;

using System.Web.UI;

using System.ComponentModel;

using System.Web.Compilation;

using System.Xml;

using System.Web.Hosting;

Trang 3

using System.Web.Caching;

namespace AspNetUnleashed

{

public class LookupExpressionBuilder : ExpressionBuilder

{

public override CodeExpression GetCodeExpression(BoundPropertyEntry entry,

object parsedData, ExpressionBuilderContext context)

{

CodeTypeReferenceExpression refMe = new

CodeTypeReferenceExpression(base.GetType());

CodePrimitiveExpression expression = new

CodePrimitiveExpression(entry.Expression);

return new CodeMethodInvokeExpression(refMe, “GetEvalData”, new

CodeExpression[] { expression });

}

public override object EvaluateExpression(object target, BoundPropertyEntry

entry, object parsedData, ExpressionBuilderContext context)

{

return GetEvalData(entry.Expression);

}

public override bool SupportsEvaluate

{

get

{

return true;

}

}

public static string GetEvalData(string expression)

{

XmlDocument lookupDoc =(XmlDocument)HostingEnvironment.Cache[“Lookup”];

if (lookupDoc == null)

{

lookupDoc = new XmlDocument();

string lookupFileName = HostingEnvironment.MapPath(“~/Lookup

➥config”);

lookupDoc.Load(lookupFileName);

CacheDependency fileDepend = new CacheDependency(lookupFileName);

HostingEnvironment.Cache.Insert(“Lookup”, lookupDoc, fileDepend);

}

Trang 4

string search = String.Format(“//add[@key=’{0}’]”, expression);

XmlNode match = lookupDoc.SelectSingleNode(search);

if (match != null)

return match.Attributes[“value”].Value;

return “[no match]”;

}

}

}

Before you can use the LookupExpressionBuilder class, you need to register it in the web

configuration file The web configuration file in Listing 31.11 includes an

<expressionBuilders> section that registers the LookupExpressionBuilder class for the

prefix lookup

LISTING 31.11 Web.Config

<?xml version=”1.0”?>

<configuration>

<system.web>

<compilation>

<expressionBuilders>

<add expressionPrefix=”lookup”

type=”AspNetUnleashed.LookupExpressionBuilder” />

</expressionBuilders>

</compilation>

</system.web>

</configuration>

The LookupExpressionBuilder uses an XML file named Lookup.config to contain a

data-base of lookup values This file contains key and value pairs A sample Lookup.config file

is contained in Listing 31.12

LISTING 31.12 Lookup.config

<?xml version=”1.0”?>

<lookup>

<add key=”WelcomeMessage” value=”Welcome to our Web site!” />

<add key=”Copyright” value=”All content copyrighted by the company.” />

</lookup>

Finally, the page in Listing 31.13 uses the LookupExpressionBuilder It contains a

Literal control that displays the value of a lookup expression named WelcomeMessage

(see Figure 31.3)

Trang 5

FIGURE 31.3 Displaying text generated by an ExpressionBuilder

LISTING 31.13 ShowLookupExpressionBuilder.aspx

<%@ Page Language=”C#” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”

“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head id=”Head1” runat=”server”>

<title>Show LookupExpressionBuilder</title>

</head>

<body>

<form id=”form1” runat=”server”>

<div>

<asp:Literal ID=”Literal1”

Text=”<%$ lookup:WelcomeMessage %>”

runat=”Server” />

</div>

</form>

</body>

</html>

Trang 6

You create a custom ExpressionBuilder by inheriting a new class from the base

ExpressionBuilder class The ExpressionBuilder class has the following methods:

GetCodeExpression—Returns the code that evaluates an expression.

EvaluateExpression—Evaluates the expression in the case of no-compile ASP.NET

pages

ParseExpression—Returns a parsed version of the expression.

The ExpressionBuilder class also supports the following property:

SupportsEvaluate—When true, the ExpressionBuilder can be used in no-compile

ASP.NET pages

When you use an ExpressionBuilder in a normal ASP.NET page, the ExpressionBuilder

returns code that is integrated into the compiled ASP.NET page The GetCodeExpression()

method returns a block of code injected into the compiled ASP.NET page class that gets

created in the Temporary ASP.NET Files folder

Because an ExpressionBuilder might be used with either a Visual Basic NET or C#

ASP.NET page, the code returned by the GetCodeExpression() method must be language

neutral This means that you must represent the code that gets executed with the CodeDom

In Listing 31.11, the GetCodeExpression() method returns an instance of the

CodeMethodInvokeExpression class This class represents an expression that invokes a class

method In this case, the CodeMethodInvokeExpression class represents the expression

LookupExpressionBuilder.GetEvalData() In other words, the ExpressionBuilder adds

code to the compiled ASP.NET page class that invokes the GetEvalData() method

contained in Listing 31.10

As an alternative to creating a normal ASP.NET page, you can create something called a

no-compile ASP.NET page, which is not compiled dynamically You create a no-compile

ASP.NET page by adding the following attribute to a <%@ Page %> directive:

<%@ Page CompilationMode=”Never” %>

NOTE

No-compile ASP.NET pages are discussed in Chapter 1, “Overview of ASP.NET.”

If you want an ExpressionBuilder to work with no-compile ASP.NET pages, you must

return the value True from the ExpressionBuilder.SupportsEvaluate property and

imple-ment the EvaluateExpression() method The EvaluateExpression is executed at runtime

when the no-compile ASP.NET page is requested In Listing 31.11, the

EvaluateExpression() method simply calls the GetEvalData() method

Trang 7

Creating HTTP Handlers

An HTTP Handler is a NET class that executes whenever you make a request for a file at a

certain path Each type of resource that you can request from an ASP.NET application has

a corresponding handler For example, when you request an ASP.NET page, the Page class

executes The Page class is actually an HTTP Handler because it implements the

IHttpHandler interface

Other examples of HTTP Handlers are the TraceHandler class, which displays

application-level trace information when you request the Trace.axd page, and the ForbiddenHandler

class, which displays an Access Forbidden message when you attempt to request source

code files from the browser

You can implement your own HTTP handlers For example, imagine that you want to

store all your images in a database table;however, you want use normal HTML <img> tags

to display images in your web pages In that case, you can map any file that has a gif or

.jpeg extension to a custom image HTTP handler The image HTTP handler can retrieve

images from a database automatically whenever an image request is made

Or imagine that you want to expose an RSS feed from your website In that case, you can

create an RSS HTTP Handler that displays a list of blog entries or articles hosted on your

website You can create an HTTP Handler in two ways You can either create something

called a Generic Handler, or you can implement the IHttpHandler interface in a custom

class This section explores both methods of creating an HTTP Handler

Creating a Generic Handler

The easiest way to create a new HTTP Handler is to create a Generic Handler When you

create a Generic Handler, you create a file that ends with the extension ashx Whenever

you request the ashx file, the Generic Handler executes

You can think of a Generic Handler as a lightweight ASP.NET page A Generic Handler is

like an ASP.NET page that contains a single method that renders content to the browser

You can’t add any controls declaratively to a Generic Handler A Generic Handler also

doesn’t support events such as the Page Load or Page PreRender events

In this section, we create a Generic Handler that dynamically generates an image from a

string of text For example, if you pass the string Hello World! to the handler, the

handler returns an image of the text Hello World!

The Generic Handler is contained in Listing 31.14

LISTING 31.14 ImageTextHandler.ashx

<%@ WebHandler Language=”C#” Class=”ImageTextHandler” %>

using System;

using System.Web;

using System.Drawing;

Trang 8

using System.Drawing.Imaging;

public class ImageTextHandler : IHttpHandler

{

public void ProcessRequest(HttpContext context)

{

// Get parameters from querystring

string text = context.Request.QueryString[“text”];

string font = context.Request.QueryString[“font”];

string size = context.Request.QueryString[“size”];

// Create Font

Font fntText = new Font(font, float.Parse(size));

// Calculate image width and height

Bitmap bmp = new Bitmap(10, 10);

Graphics g = Graphics.FromImage(bmp);

SizeF bmpSize = g.MeasureString(text, fntText);

int width = (int)Math.Ceiling(bmpSize.Width);

int height = (int)Math.Ceiling(bmpSize.Height);

bmp = new Bitmap(bmp, width, height);

g.Dispose();

// Draw the text

g = Graphics.FromImage(bmp);

g.Clear(Color.White);

g.DrawString(text, fntText, Brushes.Black, new PointF(0, 0));

g.Dispose();

// Save bitmap to output stream

bmp.Save(context.Response.OutputStream, ImageFormat.Gif);

}

public bool IsReusable

{

get

{

return true;

}

}

}

Trang 9

FIGURE 31.4 Displaying text images with an HTTP Handler

The ImageTextHandler in Listing 31.14 includes one method and one property The

ProcessRequest() method is responsible for outputting any content that the handler

renders to the browser

In Listing 31.14, the image text, font, and size are retrieved from query string fields You

specify the image that you want to return from the handler by making a request that

looks like this:

/ImageTextHandler.ashx?text=Hello&font=Arial&size=30

Next, a bitmap is created with the help of the classes from the System.Drawing namespace

The bitmap is actually created twice The first one measures the size of the bitmap required

for generating an image that contains the text Next, a new bitmap of the correct size is

created, and the text is drawn on the bitmap After the bitmap has been created, it is saved

to the HttpResponse object’s OutputStream so that it can be rendered to the browser

The handler in Listing 31.14 also includes an IsReusable property, which indicates

whether the same handler can be reused over multiple requests You can improve your

application’s performance by returning the value True Because the handler isn’t

maintain-ing any state information, there is nothmaintain-ing wrong with releasmaintain-ing it back into the pool so

that it can be used with a future request

The page in Listing 31.15 illustrates how you can use the ImageTextHandler.ashx file

This page contains three HTML <img> tags that pass different query strings to the handler

(see Figure 31.4)

Trang 10

LISTING 31.15 ShowImageTextHandler.aspx

<%@ Page Language=”C#” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”

“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head id=”Head1” runat=”server”>

<title>Show ImageTextHandler</title>

</head>

<body>

<form id=”form1” runat=”server”>

<div>

<img src=”ImageTextHandler.ashx?text=Some Text&font=WebDings&size=42” />

<br />

<img src=”ImageTextHandler.ashx?text=Some Text&font=Comic Sans MS&size=42” />

<br />

<img src=”ImageTextHandler.ashx?text=Some Text&font=Courier New&size=42” />

</div>

</form>

</body>

</html>

Implementing the IHttpHandler Interface

The big disadvantage of a Generic Handler is that you cannot map a Generic Handler to a

particular page path For example, you cannot execute a Generic Handler whenever

someone requests a file with the extension gif If you need more control over when an

HTTP Handler executes, you can create a class that implements the IHttpHandler interface

For example, the class in Listing 31.16 represents an Image HTTP Handler This handler

retrieves an image from a database table and renders the image to the browser

LISTING 31.16 App_Code\ImageHandler.cs

using System;

using System.Web;

using System.Data;

using System.Data.SqlClient;

using System.Web.Configuration;

namespace AspNetUnleashed

{

Ngày đăng: 06/07/2014, 18:20

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN