Friday, February 25, 2011

Debugging an HTTP Handler (*.ashx) in ASP.NET 2.0

source : http://www.15seconds.com/Issue/060406.htm?voteresult=5

By Dina Fleet Berry



  • print this article 

  • email this article to a colleague 

  • suggest an article

    Click Here! 
    Click Here! 
    MARKETPLACE
    Image Ad$112B in Govt IT Opportunities by 2015
    Maximize Your Market Position: FREE Summary of Federal IT Forecast 2010-2015
    www.INPUT.com
    Image AdNetwork Management Software
    Discover, Map, Monitor & Manage all network devices, Apps, AD, Services, etc. Try Free/Trial Edition
    www.OpManager.com
    Image AdBandwidth Monitoring w/ NetFlow Analyzer
    Monitor Bandwidth, Identify top talkers, do better capacity planning. Try Now!
    www.NetFlowAnalyzer.com

    A handler is responsible for fulfilling requests from a browser. Requests that a browser manages are either handled by file extension (or lack thereof) or by calling the handler directly. Only one handler can be called per request. A handler does not have any HTML static text like .aspx or .ascx files. A handler is a class that implements the IHttpHandler interface. If you need to interact with any Session information, you will also need to implement IRequiresSessionState. If you want to make an asynchronus handler, you will need to implement the IHttpAsyncHandler interface instead of the IHttpHandler interface.
    Calling a Handler by File Extension

    A handler can be invoked by any file extension that is mapped via the web.config and the IIS file extension mappings. You can have a file named something.billybob where 'billybob' is the file extension, or you can have no file extension at all such as http://web/handler/file where a request for 'file' without an extension invokes a handler mapped to *.* or the directory as *.
    Calling a Handler Directory

    The code file for the handler has the file extension of 'ashx' on the web server. This file can be called directly via a browser without having to set up web.config or IIS file extension mappings. For example: http://web/handler/handler.ashx. Some examples of this hander type are photo albums, RSS feeds, and blogging sites. Each of these is a good example of work that can be better accomplished without standard HTML. A photo album involves directory crawling and responding with pictures. A RSS feed returns information in the correct format.
    Trace.axd as an Example Handler

    An example of a handler that is invoked by file extension is the Trace.axd file used for debugging. In order to invoke the Trace.axd handler, you configure the website for tracing by adding a trace section to web.config:
    
        
            
        
    
    
    and call the trace.axd file from the root of the website such as http://localhost/trace.axd.
    Required IIS Mappings for Handlers Called by File Extension

    Handlers that are invoked based on a request's file extension require configuration in web.config and in the IIS file extension mapping. In order to see the file mapping of the *.axd file, open the IIS Manager and configure the application. Go to the 'Mappings' tab and scroll down until you see the .axd file extension.

    Double-click on the .axd extension in order to see more details about this mapping.

    Invoking handlers by file extension or no extension gives you flexibility about what is called and when. There are many articles on the web about file extension handlers so this article will focus on the handler that is called directly.
    Creating a Handler

    In order to create a handler code file, you need a web site in Visual Studio 2005 (or Visual Studio 2003 for a .NET 1.x handler). For a new website, select 'ASP.NET Web Site'.

    This will create a web site with an App_Data directory and the default.aspx file. You won't use the default.aspx so you can either leave it alone or delete it.
    You will need to create the web.config and the handler file by clicking on the website in the Solution Explorer and add new items of 'web.config' and 'Generic Handler'.

    The handler code file will look like:
    <%@ WebHandler Language="C#" Class="Handler" %>

    using System;
    using System.Web;

    public class Handler : IHttpHandler {

        public void ProcessRequest (HttpContext context) {
            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World");
        }

        public bool IsReusable {
            get {
                return false;
            }
        }

    }

    At this point, build the project and set the handler.ashx file as the startup file. Start debugging. You will be prompted to allow the process to change your web.config to allow debug. Unless you want to type in the change to allow debugging yourself (""), accept this change.

    In my brower, because my desktop is set-up to parse text/plain as XML, I get an error that looks like:

    The handler.ashx that Visual Studio provided needs to be fixed before it will work. So change the Content Type from 'text/plain' to 'text/html'. Build, and debug again. You should get a response that looks like:

    Handler.ashx

    The handler.ashx file implements the IHttpHandler interface and has two methods of 'ProcessRequest' and 'IsReusable'. The 'ProcessRequest' is your main method where you put your code. The 'IsReusable' method is set to true by default and indicates whether another request can use the IHttpHandler instance. If the instance can be reused mark it true -- this will improve the speed of the handler, and reduce the work your server will have to do. But if your instance should not be reused, due to state or because it is ansychronous, you should set IsReusable to false.
    Session State

    Before continuing, change the handler.ashx code to implement the IRequiresSessionState interface. If you need read-only access to the Session, implement the IReadOnlySessionState interface. Both interfaces are in the System.Web.SessionState namespace which you will need to add with the 'using' syntax. The code should now look like:
    <%@ WebHandler Language="C#" Class="Handler" %>

    using System;
    using System.Web;
    using System.Web.SessionState;

    public class Handler : IHttpHandler , IReadOnlySessionState{

        public void ProcessRequest (HttpContext context) {
            context.Response.ContentType = "text/html";
            context.Response.Write("Hello World");
        }

        public bool IsReusable {
            get {
                return false;
            }
        }

    }

    Set a break point for the first line in the class and start debugging again.
    Handling Issues with a Debug Build

    When you use a debug build, you have the full resources of the Visual Studio debugger, all .NET Framework namespaces, and any system utilities and applications. The Visual Studio Debugger allows you to view the call stack, local variables, any watch variables, etc. You are probably familiar with using these features to some degree. However, with a HTTP Hander, debugging is much more important because the only visual indication of a bug is whatever you code into the content.
    Handling Issues with a Release Build

    The release build is different from the debug build in both features and performance. When you are using a release build, it is probably in a production environment. As such, you will need to use a different set of tools to find your issues.
    Debugging with System.Diagnostics Namespace

    The Diagnostics namespace has many classes to help with debugging in release and debug mode. If you are debugging in release mode, you should use the Trace class. If you are debugging in debug mode, you should use the Assert class. This article doesn't cover all the abilities of this namespace so you should investigate what class will help you solve your immediate problem.
    In order to show these classes in action, change the code to use the namespace and use an infinite loop. The assertion is throw when the expression in the assertion is false, so the assertion will throw when the counter is no longer less than 10.
    <%@ WebHandler Language="C#" Class="Handler" %>

    using System;
    using System.Web;
    using System.Web.SessionState;
    using System.Diagnostics;

    public class Handler : IHttpHandler , IReadOnlySessionState{

        public void ProcessRequest (HttpContext context) {

            context.Response.ContentType = "text/html";
            context.Response.Write("Hello World");

            int i=0;

            while (1!=0)
            {
                Debug.Assert(i<10);
                i++;
            }

        }

        public bool IsReusable {
            get {
                return false;
            }
        }

    }

    Build and debug. Since there are no breakpoints set, the debugger will become active again when the assertion is hit. This is great if you know what the error is you are getting and can test for it. The first thing that happens is an assertion window pops up with information about the assertion. If you want the debugger to become active, click the "Retry" button. This will bring up the debugger at that assertion code line.
    If you know a general code location you would like to look at instead of a specific Boolean statement to test for, you should use the Debugger.Break statement in your code. This will pop up the debugger as well. If you want to look at preconditions and then stop at the error, you can combine these two statements to quicken your debugging process. An example of that code is below:
    <%@ WebHandler Language="C#" Class="Handler" %>

    using System;
    using System.Web;
    using System.Web.SessionState;
    using System.Diagnostics;

    public class Handler : IHttpHandler , IReadOnlySessionState{

        public void ProcessRequest (HttpContext context) {

            context.Response.ContentType = "text/html";
            context.Response.Write("Hello World");

            Debugger.Break();

            int i=0;

            while (1!=0)
            {
                Debug.Assert(i<10);
                i++;
            }
        }

        public bool IsReusable {
            get {
                return false;
            }
        }

    }

    You can use the Debug.Write, Debug.WriteIf, Debug.WriteLine, and Debug.WriteLineIf to print to the Output window during a debug session. This could help you view the state of the HTTP Handler.
    If you want to track down an issue in a release build, you will have to have a way of peering into the code. One way to do that is to add EventLog.WriteEntry statements into your code. This allows you to add information to the event log as the HTTP Hander is running. The WriteEntry method is heavily overloaded so you will need to determine the best method for your use. If you want to see information as a simple information entry in the event viewer, you just use one String argument. The Event Viewer needs to know the "Source" of the event so let's name it "HTTPHandler - DebugArticle". This should be easy to see in the Event Viewer. The code looks like:
    <%@ WebHandler Language="C#" Class="Handler" %>

    using System;
    using System.Web;
    using System.Web.SessionState;
    using System.Diagnostics;

    public class Handler : IHttpHandler , IReadOnlySessionState{

        public void ProcessRequest (HttpContext context) {

            context.Response.ContentType = "text/html";
            context.Response.Write("Hello World");

            int i=0;

            // Create an EventLog instance and assign its source.
            EventLog myLog = new EventLog();
            myLog.Source = "HTTPHandler-DebugArticle";

            while (i<100)
            {
                if (i/10==0)
                {
                    // Write an informational entry to the event log.
                    myLog.WriteEntry("Writing to event log: i is divisible by 10.");
                }
                i++;
            }

        }

        public bool IsReusable {
            get {
                return false;
            }
        }

    }

    Build a release version of the handler and call it. The output should only include the "Hello World" text. Open the Event Viewer, Application log. You should see several postings from the source of "HTTP Handler - DebugArticle".

    If you open one of the events, you should see a simple output:

    There are also classes to interact with the Performance monitor, and processes as well as several classes to help with logic flow.
    Attaching to a Process to Debug a Running HTTP Handler

    Another method of finding your issues is to attach to a process that contains the HTTP Handler. If you are running multiple websites where each website is in it's own process space, you may have to figure out the process id. The easiest way is to have your handler tell you. The System.Diagnostics namespace includes a class called Process which will help you determine the current process's id. In order to find the id, let's send the id to the event viewer by changing the code to:
    <%@ WebHandler Language="C#" Class="Handler" %>

    using System;
    using System.Web;
    using System.Web.SessionState;
    using System.Diagnostics;

    public class Handler : IHttpHandler , IReadOnlySessionState{

        public void ProcessRequest (HttpContext context) {

            context.Response.ContentType = "text/html";
            context.Response.Write("Hello World");

            int i=0;

            Process.GetCurrentProcess().Id.ToString();

            // Create an EventLog instance and assign its source.
            EventLog myLog = new EventLog();
            myLog.Source = "HTTPHandler-DebugArticle";
            myLog.WriteEntry("Process Id is " + Process.GetCurrentProcess().Id.ToString());

            while (i<100)
            {
                if (i/10==0)
                {
                    // Write an informational entry to the event log.
                    myLog.WriteEntry("Writing to event log: i is divisible by 10.");
                }
                i++;
            }

        }

        public bool IsReusable {
            get {
                return false;
            }
        }

    }

    The important code line here is in the loop and is an alteration to the string in the myLog.WriteEntry:Process.GetCurrentProcess().Id. The following figure shows what the Event Viewer entry looks like:

    Now that you know the process id, you need to find this id in the Task Manager. In order to see process ids in the Task Manager, click to the Process tab then click on View and choose Select Columns. Click on PID (Process Identifier) and OK out of the Dialogs. The list of processes should now include the PID, which you can sort by if you click on the column name. Once you find the right process id in the list, right click on it and choose Debug. This will start Visual Studio. You will have to open your code file from Visual Studio and debug at that point.
    Summary

    An ASP.NET HTTP Handler is a simple class that allows you to process a request and return a response to the browser. The handler gives you access to the current web context and the session state. The default 'Generic Hander' that Visual Studio 2005 gives you may not work with its current code. With a few changes, working with the System.Diagnostics namespace will have you writing HTTP handlers that build and debug successfully.
  • Friday, February 4, 2011

    Modify an existing constraint

    Modify an existing constraint requires next steps
    - drop the existing constraint


    ALTER TABLE [dbo].[tblA] 
    DROP FK_tblA_a

    -adding this constraint again 


    ALTER TABLE [dbo].[tblA]  WITH CHECK ADD  CONSTRAINT [FK_tblA_a] FOREIGN KEY([IdCol])
    REFERENCES [dbo].[tblB] ([ID])
    ON UPDATE CASCADE
    ON DELETE CASCADE

    Deploying Reports

    By Vasant Raj, 2007/06/05

    Total article views: 17515 | Views in the last 30 days: 242

    Introduction

    Tight integration with the .NET environment is the important feature for the popularity of Microsoft SQL Server 2005. As a result, it is possible to perform the some of the common tasks by using different options. This allows the developers/administrators to do their work by selecting the options that they are comfortable with. For example, you can manage/administer the report sever using the SQL Server Management Studio OR the web-based Report Manager. In this article, will look at the various ways for deploying reports on the report server. [It is assumed that the reports are already created]

    How to deploy reports?

    It is possible to deploy the reports in 3 ways:
    • Using the BI Development studio.
    • Using the SQL Server Management Studio.
    • Programmatically. [Using the RS.EXE utility]
    Using BI Development studio:
    1. Open the Project Properties dialog-box and set the TargetServerURL. It is the URL of the report server, on which the reports will be deployed. [Figure 1]

      [Figure 1] 
    2. Right-Click on the Project and select Deploy [Figure 2]. This will deploy the reports and Data-sources defined in the project on the specified report server.

      [Figure 2]
    Using SQL Server Management Studio:
    1. Connect to the Reporting services database.
    2. Right-click on Home and select the desired options. [Figure3]

      [Figure 3]
    Select New Folder to create a new folder on the server. Select New Data Source option for defining a data-source for the reports. Select Import File for adding/deploying the reports on the server.
    Using the RS.EXE utility:
    • It is a Command-line utility.
    • Used for performing Deployment and Administrative tasks programmatically.
    • Executes the RSS file. [Reporting Services Script file]
    • Command to execute:
      rs i MyRSS.rss -s http://localhost/reportserver
      
    • Parameters can also be passed. These parameters are the global variables in the RSS script file. Multiple parameters can be passed.
      For example:
      rs i MyRSS.rss -s http://localhost/reportserver -v param1="value1" -v param2="value2" 
    How to write the RSS file:
    • VB.NET code file [with rss extension].
    • Can contain user-defined function and global parameters. The value for the global parameters has to be supplied from the command line.
    • It should have a Main () procedure.
    • By default, the namespaces System.IO, System.Xml and System.Web.Services are included.
    • A reference variable rs for the reporting services web service is generated automatically when the script is executed using the RS.EXE utility. This variable allows access to all the functionality of web service class library [of reporting services].

    Sample code:

    Extract the MyReport.zip file in the D\MyReports folder.
    The sample RSS file creates a data-source, which points to the Northwind database on the (local) sql server instance using Windows authentication. The function used is: CreateDataSource(name,extensionconnectionstring)

    Example:
    CreateDataSource("MyDataSource", "SQL", "Data Source= (local);Initial Catalog=Northwind")
    It also publishes a sample report using the CreateReport function.
    CreateReport(NameofReportParentFolderOverwriteReportDefinitionProperties)

    Example:
    CreateReport(MyReport, /MyReports, False, definition, Nothing)
    If report contains any external images, then it has to be also deployed as a resource. This is not required if the image is embedded in the report. The function used is: CreateResource(ImageName,ParentFolderOverwriteDefinitionMIME typeProperties)

    Example:
    CreateResource(ImageName, parentPath, False, definition, "image/jpeg",Nothing)
    For executing the rss file, open the command prompt and set the directory to D:\MyReports and run the following command:
    rs -i MyRSS.rss -s http://localhost/ReportServer
    Output will look like:
    After successful execution, MyReports folder will be created on the report server. It can be viewed using the Report Manager.

    Conclusion

    The reports can be deployed using the above 3 methods. Reporting Services script files can be used to run any of the Report Server Web service operations like creating schedules, subscriptions, security settings, etc. Replicating report server would be easy using the Reporting Services script file.

    By Vasant Raj, 2007/06/05

    Total article views: 17515 | Views in the last 30 days: 242