Monday, July 16

Using HTTP Handler for dynamic image generation

I was working on a project recently that needed bar charts to be created dynamically. We were not using sql reporting for this project. The bar chart needed to be changed/ updated based on certain criteria chosen from date controls, dropdowns etc.

One of the ways to achieve this is to create the image server side, store it on the disk on server and set the ImageUrl property of the image on the page to that saved image and send it to the browser.
This approach works but leads to addditional maintenance tasks, such as cleaning up old images, managing disk space etc...

One of the short comings of the asp.net image control Vs the image control in WinForms is that it lacks a property called "Bitmap" which allows you to assign a dynamically generated bitmap to the image control.

The only property exposed is the "ImageUrl".

I heard about http handlers and modules in podcats from polymorphic podcasts where Miguel Castro was explaining the use of HttpHandler to process certain file types.

Here is a formal definition from msdn : "An ASP.NET HTTP handler is the process (frequently referred to as the "endpoint") that runs in response to a request made to an ASP.NET Web application. The most common handler is an ASP.NET page handler that processes .aspx files. When users request an .aspx file, the request is processed by the page via the page handler.


HTTP handlers have access to the application context, including the requesting user's identity (if known), application state, and session information. When an HTTP handler is requested, ASP.NET calls the ProcessRequest method on the appropriate handler. The handler's ProcessRequest method creates a response, which is sent back to the requesting browser. As with any page request, the response goes through any HTTP modules that have subscribed to events that occur after the handler has run."


Scott Hanselman says : "Remember, an HttpHandler is the kind of thing you want to use when an HttpRequest is going to return a file or image to the browser. Basically anything other than a standard page. True, you could use a page, remove all the HTML from the ASPX part, and return stuff in Page_Load, but that's not really what pages are for, right? Also, Pages are themselves an HttpHandler (returned by PageHandlerFactory) so why not write your own HttpHandler?"

The processRequest for our bar chart image handler looks like this.

public void ProcessRequest (HttpContext context)
{
mPresenter = new ChartsPresenter(this);
ProcessQueryString(context);
DrawBarChart(context);
}

When the bitmap generation is completed, we output the bitmap in this fashion

context.Response.ContentType = "image/gif";
bitmap.Save(context.Response.OutputStream,
System.Drawing.Imaging.ImageFormat.Gif);


We associate the ImageUrl property of the image to the http handler created to output the bar chart. Here is an abstract base class for creating http handlers that return proper error codes in case of problems. Phil Haack wrote it.


Wednesday, July 11

Databind dropdowns to Enums

Here is how you do it.

   20     private enum ReportTypes : int
   21     {
   22         ByVendor = 1,
   23         ByCategory = 2,
   24         ByType = 3
   25     }
35 protected void Page_Load(object sender, EventArgs e)
   36     {
   37         if (!IsPostBack)
   38         {
   44             ddlReportTypes.DataSource = Enum.GetNames(typeof(ReportTypes));
45 ddlReportTypes.DataBind();
   46         }
   47     }
   48     protected void ddlReportTypes_SelectedIndexChanged(object sender, EventArgs e)
   49     {
   50         ReportTypes rType =
   51             (ReportTypes)Enum.Parse(typeof(ReportTypes), ddlReportTypes.SelectedValue);
   52         switch (rType)
   53         {
   54             case ReportTypes.ByVendor:
   56                 break;
   57             case ReportTypes.ByCategory:                
   60                 break;
   61             case ReportTypes.ByType:
   62                 break;
   63         }
   64     }

Wednesday, July 4

Web.Config Gotcha

Midway into the project we sometimes realize that the intellisense in the web.config has vanished all of a sudden. The culprit being this line.

10
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

Removing the xmlns attribute from the configuration tag brings back the intellisense for the Web.Config.

10 <configuration>

I saw this on one of the dnrtv shows, so credit goes to the author Miguel Castro.




Labels:


Tuesday, July 3

Setting up Windows Authentication for Intranet Websites

 Recently I was put on a project that needed to harness the built in windows security for user authentication. Idea was to allow access only tousers of subscribed to certain groups. Once authenticated, based on the group the user is subscribed to, I needed to perform custom actions. 

The configuration started with the Web.Config. I added the authentication andauthorization sections to the Web.Config, specifying the authentication type and the groups authorized to access the site.

We deny access to anonymous users. Also, with the "Impersonate clause" we tell ASP.NET
to run using the permission/priveledges of the authenticated user
instead of the default asp_net user.

   37         authentication mode="Windows"        
   38         authorization
   39             allow roles="MSDomain\Buyers,MSDomain\Clerks,MSDomain\Receivers"
   40             deny users="*"            
   41         authorization
   42         identity impersonate="true"        
In order to be able to find out whether a user belongs to a particular group and to get a list of groups a user is subscribed to, we needed to
specify a "roleManager" config section and set the default provider to "AspNetWindowsTokenRoleProvider". Until this is done, the any code written
to check whether the user is part of a group/list of groups will not work.
"Role Manager" helps us manage groups(roles) and perform group based authorization
in the applicaion. We need the role manager to help us identify the groups of which the authenticated user is a part of and perform actions like wise.
Msdn article about role management says:
"The main benefits of using role manager are that it allows you to look up users' roles without writing and maintaining code. Additionally, the 
role providers offer a consistent way for you to check the role membership of your users, regardless of the underlying data store. Therefore, 
if your role store were to change tomorrow, you would only need to change the configuration settings to make your code work."

 roleManager enabled="true" defaultProvider="WindowsTokenRoleProvider" >

The default role providers are as follows:
1. SqlRoleProvider
 - role information kept in SQL Server
2. WindowsTokenRoleProvider
 - read-only provider that retrieves role information for a 
   Windows user account based on the account's Windows security 
   group membership
3. AuthorizationStoreRoleProvider
 - used if your application uses Authorization Manager (AzMan)
In my case, all I needed was to redirect user to corresponding portion of the site depending on their role, hence read-only role provider was
sufficient.
Msdn article says "The Windows security system acts as role store for this 
provider, so no additional configuration is required to set up the role store"
 
Once the user is authenticated, we need to check if the user is part of a particular group, if yes, then perform the custom action.
Below is the code required to validate whether a user is part of a inranet group.

  120         if (User.IsInRole   (WindowsGroupSettings.SettingFor.Buyers))
  121         {
  122             if (this.LoadPricesForBuyer != null)
  123             {
  124                 _buyerName = User.Identity.Name;
  125                 LoadPricesForBuyer(this, EventArgs.Empty);
  126             }
  127         }

To get a list of groups a user is part of use the following code:


  140         if (!IsPostBack)
  141         {
  142             gvRoles.DataSource = Roles.GetRolesForUser(User.Identity.Name);
  143             gvRoles.DataBind();
  149         }
 
Notice that I have used the WebNavigator, MVP pattern in this project. :)
I am having a torrid time fighting the fonts/html in post that contain code copied using copySourceAsHtml, 
especially code containing tags.

Labels: , ,


This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]