Providing images from. NET Assemblies (i)

Source: Internet
Author: User
Tags filter define exception handling finally block httpcontext iis valid root directory
Program Summary: Most WEB site user interface needs to have images, these images are usually stored on disk. This article describes how to provide an image from an assembly. Providing images from an assembly avoids the spread of many files on disk, simplifies the installation and configuration of your Web server, and improves the security of your images. (This article contains some links to English-language sites)

Apply to:
Microsoft®.net Framework version 1.0 and 1.1
Microsoft®visual c#®
Microsoft®asp.net

Download the MFRImages.exe sample file. The download includes Readme.htm, which explains how to configure the sample.

Directory:
Brief introduction
Overview of issues
Provide image
Providing images from ASPX pages
To provide an image from a custom handler

Brief introduction

Often you hear programmers who have written Windows controls and then turn to the Web complaining: "Why can't you store images in the same assembly as a control?" "The answer is yes, you just need to know how to do it." This article describes how to provide an image from within an assembly and provides two ways to retrieve an image. Download the MFRImages.exe at the top of this page to get a complete picture of the sample code discussed below.

Overview of issues

Images on a Web site are usually referenced by a URL, for example. /uploadpic/2007-2/2007262311518.gif It tells the Web client where to look for images. In a Web page, images and text are downloaded separately. Images are usually stored in a subdirectory of the WEB server named/images, and the page simply provides references to these images so that they can be displayed in the client's browser.

This is also true when you create a custom control-the image is usually stored on disk before it is downloaded by the user. As the creator of the control, you might want to be able to provide an assembly that includes not only the controls but also the corresponding default images. It is useful to keep the control self-contained because it requires fewer users to configure. (Users who are responsible for the configuration may forget to copy a large number of image files to the production server, causing dissatisfaction among other users.) )

Another reason you want to bind resources to an assembly may be to ensure that users cannot change these resources-for example, for a company brand, you should always use a specific image, not a user who mistakenly saves the wrong image (such as incorrect typeface or color) to disk. If your assembly has been strictly named, you can test to make sure that the Assembly has not been tampered with when the assembly is loaded.

The main problem with providing images from an assembly is that HTTP needs to get an image through a URL-you can't just return a string of bytes directly into the HTML to the user, expecting the image to be displayed correctly. It is necessary to try to redirect an image request to a resource within an assembly, and I will describe two methods in this article.

Before continuing with the following, there is a problem to be noted. If there are no other configurations on the WEB server, it is not possible to provide a completely independent control that renders the image correctly. You will also need to create additional files (at least one) on the server, or make some changes to the IIS metabase to provide the images to the client. However, with these simple changes, you can easily provide images from any assembly.

Provide image

Now that the key to the problem is to provide the image, let's get to the point. When information is passed from the caller, we need to find a way to load the image and return the image in the response stream. Note that the image provided in this example has only a. gif type-to provide other types of images, you need to infer the content type and image format with the image extension.

The following function shows how to load an image from a given assembly and return it to the client via the HttpResponse stream. We'll use this function as the basis for the following code and add more useful features, such as exception handling and image caching, to the next section. I'll define this function as a static function in the Manifestimageloader class.

public class Manifestimageloader
{
public static void RenderImage (
string assembly, string image, HttpContext context)
{
Assembly Resourceassem = Assembly.Load (Assembly);

Get Resources
using (Stream ImageStream =
Resourceassem.getmanifestresourcestream (image))
{
If you can, write it out
using (System.Drawing.Image theimage =
System.Drawing.Image.FromStream (ImageStream))
Response. ContentType = "Image/gif";
Theimage.save (context. Response.outputstream, imageformat.gif);
}
}
}



The function RenderImage accepts the assembly name, image name, and response flow. With a valid assembly name and image name, it is easy to load an image and return it to the output stream. Load the assembly first, and then use the Assembly.GetManifestResourceStream function to return the data stream of the named resource (image in this instance). You need to add a using clause for System.Reflection and System.IO to enable it to compile and reference the System.Drawing assembly.

After you have an image stream, you can use the Image.fromstream () method to construct the image from that byte stream-note that we are using an image class in System.Drawing instead of System.Web.UI.WebControls Class that has a similar name in it because the former has permission to access the WIN32 image function, and the latter contains markup in the Web control.

You may not be familiar with the C # using syntax, which contains code in the Try/finally block, which ensures that you call Dispose of the items in parentheses. Now that we can provide an image from the assembly, we first need to be able to create a URL for the image. The first method is to use the. ASPX page.

Providing images from ASPX pages

The first method of providing an image needs to be used. ASPX page, which typically resides at a location on the server. The page itself does not contain content-its primary function is to retrieve parameters from the URL and use these parameters to retrieve the image.

For example, there is a page named imagefromaspx.aspx located in the root directory of the Web site. You can then use the following URL encoding syntax in HTML to define all the images provided from this page. Here we provide a title image named Winxp.gif.





In the URL, we define the path to the ASPX page and then define two parameters, one for the assembly name (Imageserver in this instance) and the other for the image name. This can be risky in terms of security, so later in this article I'll describe an encryption method that you can use for this data.

In the code for the ASPX page, you can write the following:

private void Page_Load (object sender, System.EventArgs e)
{
Retrieving parameters
String assembly = request.querystring["Assem"];
String image = request.querystring["image"];

and load the image
Manifestimageloader.renderimage (assembly, image);
}



What the code does is parse the parameters based on the request, and then call the RenderImage function we wrote earlier. As you can see, it's not hard to achieve. But it has a drawback that all requests for images need to pass the same URL. In other words, each custom control must know the location and name of the imageserver.aspx file to provide the image. How to avoid this limitation is the subject of the next section.

To provide an image from a custom handler

If you've never been in contact with a handler before, I'll probably introduce it here. Handlers are objects used to implement the IHttpHandler interface. When a request containing a given file name extension passes through the ASP.net pipeline, the handler is invoked for a specific verb (such as POST, get, and so on) or a set of verbs.

Typically, ASP.net checks the requested file name extension and passes the request to the handler associated with the extension. With this knowledge, we can create a handler that associates it with its own file name extension (so that ASP.net knows we're calling the handler, not the other content) and provides the image in that way.

The following code shows a simple handler that uses the RenderImage function declared above.

public class Manifestresourcehandler:ihttphandler
{
<summary>
Processing Image Requests
</summary>
<param name= ' context ' >the current HTTP context</param>
void Ihttphandler.processrequest (System.Web.HttpContext context)
{
Get the assembly name and resource name from the request
String assembly = Context. request.querystring["Assem"];
String image = Context. Request. querystring["image"];

Then load the image and return it to the caller
Manifestimageloader.renderimage (assembly, image);
}

<summary>
This handler can be reused and does not require a loop
</summary>
BOOL Ihttphandler.isreusable
{
get {return true;}
}
}



This code is very similar to the code shown above for the ASPX page-read the arguments from the URL that came, and then pass those parameters to the RenderImage function.

Now, to use a handler to provide an image, we need to use a different URL. In this instance, you need to create a fictitious file name extension (that is, an extension that does not exist in IIS), so that the image request can be sent to the correct handler. In this example I will use the extension "MFR" (for "manifest resource"). The image request now looks a bit like the following description.





Note that I have not yet specified the path to the resource, just specified the file extension. mfr.

The primary benefit of using handlers is that you can invoke the program for all requests, regardless of their path. Two additional steps are required to enable the handler to work. First, you need to modify the web.config to specify a new handler:

<configuration>
<system.web>
...
<add verb= "Get" path= "*.mfr" type= "Imageserver.manifestresourcehandler, Imageserver"/>
</system.web>
</configuration>



The type in the configuration file described above defines the type and assembly that implements the handler. Note that verb attributes are case-sensitive and should therefore be set to get instead of other case. The Assembly itself needs to reside in the binary directory of your WEB site or be installed in the global Assembly cache (GAC).

Second, you need to edit the configuration of the Web server in IIS management. Click the properties of the Web site that you want to change, select the Home Directory tab, and then click Configuration (Configuration). A window similar to the following window will be displayed.


Click the Add button to create an entry for the. mfr file type. Each extension is mapped to an ISAPI filter that handles resource requests. For ASP.net, a aspnet_isapi.dll filter. This library resides under the installed Framework on disk, so to set all requests for the. mfr extension to pass the appropriate ISAPI DLL, you need to set the following:

Version path
1.0 C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\aspnet_isapi.dll
1.1 C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll

The rest of the settings appear in the following image. Note that you must clear the check box for Verify that file exists (check for file presence), otherwise the handler will never be invoked (because the actual. mfr file does not exist on the disk).

You should now be able to run the handler. In the browser, type the URL to the resource that is mapped to the assembly:

If you receive a not-requested image, but an exception (such as "' null ' is not a valid value for ' stream '), you may encounter some minor problems that we have not yet dealt with in our code-what if the image is faulty? We will correct the problem and some other minor issues in the next section.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.