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

ASP.NET 4 Unleased - p 150 pdf

10 187 0

Đ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

Nội dung

ptg 1464 // 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. Creating a Custom ExpressionBuilder 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. CHAPTER 31 Working with the HTTP Runtime From the Library of Wow! eBook ptg 1465 Creating a Custom ExpressionBuilder 31 . 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; From the Library of Wow! eBook ptg 1466 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); } CHAPTER 31 Working with the HTTP Runtime From the Library of Wow! eBook ptg 1467 Creating a Custom ExpressionBuilder 31 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). From the Library of Wow! eBook ptg 1468 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> CHAPTER 31 Working with the HTTP Runtime From the Library of Wow! eBook ptg 1469 Creating a Custom ExpressionBuilder 31 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. From the Library of Wow! eBook ptg 1470 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; CHAPTER 31 Working with the HTTP Runtime From the Library of Wow! eBook ptg 1471 Creating HTTP Handlers 31 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; } } } From the Library of Wow! eBook ptg 1472 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 nothing wrong with releasing 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). CHAPTER 31 Working with the HTTP Runtime From the Library of Wow! eBook ptg 1473 Creating HTTP Handlers 31 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 { public class ImageHandler : IHttpHandler From the Library of Wow! eBook . %> 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. 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”. 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

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