ASP.NET Charting: Rendering Options

With the release of .NET 3.5 SP1, MS has released a sub-set of the Dundas charting component. They also put together a neat little solution that’ll let you run a number of examples/samples locally so you can get your hands dirty. If you’re looking to do any work with the charting components, or just play around getting these samples should definitely be your first step as the basics will be self-explanatory. The link for that is here.

Now that we got the boring introductory stuff out of the way; the .NET charting component gives you a few different choices when it comes to rendering your chart/image.

Temp directory/ImageTag/ImageUrl Method

This is what I’d consider the simple/out-of-the-box method. Basically, when you create your chart either in the designer or in a code-behind you can specify where the chart should live. This means that ASP.NET will create a chart based on some data that you provide, dump it in a temporary directory, and then you’ll refer to it just as you would any other image.

In other words, your designer markup may look like this:

<asp:chart id="Chart1" 
  runat="server" 
  Height="296px" 
  Width="412px" 
  ImageLocation="~/TempImages/ChartPic_#SEQ(300,3)" 
  Palette="BrightPastel" 
  BorderDashStyle="Solid" 
  BackGradientStyle="TopBottom" 
  BorderWidth="2" 
  backcolor="#D3DFF0" 
  BorderColor="26, 59, 105"
>

And, at runtime, the server will spit out something like the following:

<img id="Chart1" 
  BorderDashStyle="Solid" 
  src="/WebSamples/ChartImg.axd?i=chart_00090164d2f6498095a78f42f0b28216_1.png&amp;g=772eca8a160b4cb291bfe41a00e762a7" 
  alt="" 
  style="height:296px;width:412px;border-width:0px;" 
/>

Look familiar? That’s roughly what an ASP:Image control would render to had you dropped one of those onto the page. The only difference is that your SRC tag points to a HttpHandler that you specified in your web.config.

In any case, using this method is very straight forward and your client’s browsers will cache your charts just as they would any other image. Of course, the image file that gets cached will look like this:

ChartImg.axd?i=chart_00090164d2f6498095a78f42f0b28216_0.png&g=ec1fd46ebf42485894656b42606e5b27

…The MSDN documentation states that for static data, this caching improves performance. However, in my experimenting even with static data a refresh of the page causes the querystring parameters to change…which means you will need to pull it back down from the server, which also means the browser cached it for nothing. (Although this is what my experimenting indicated, I’m wondering if I missed something. Information to the contrary is welcome…anyone…?...crickets?)

Binary Streaming Method

Now, if you looked at the MS Chart Samples solution, you’ll notice that I’m skipping a couple of “rendering methods” here. That’s largely because I’m thinking if you’re still reading this, you already know you can render a chart in an iFrame, and because their guidance on rendering charts within legacy websites is essentially “use Binary Streaming”.

Binary Streaming is implemented by doing either one of the following

Keep in mind an asp:Image control is getting translated to an IMG tag anyway. In both cases, SomeChart.aspx contains the designer construct for a chart. Something like the following [which is snipped]:

<img src="SomeChart.aspx" width="412" height="296" alt=""/>

Or…

<asp:Image id="Image1" runat="server" ImageLocation="SomeChart.aspx" 
/>

Keep in mind an asp:Image control is getting translated to an IMG tag anyway. In both cases, SomeChart.aspx contains the designer construct for a chart. Something like the following [which is snipped]:

<%@ Page Language="c#" Inherits="Samples.SomeChart" CodeFile="SomeChart.aspx.cs" %>
<asp:chart id="Chart1" runat="server" height="296px" width="412px" 
    imagetype="Png" palette="BrightPastel" backcolor="#F3DFC1" rendertype="BinaryStreaming"
    borderdashstyle="Solid" backgradientstyle="TopBottom" borderwidth="2" bordercolor="181, 64, 1">
    <series>
        <asp:Series ChartTypeName="SplineArea" Name="Series1" BorderColor="64, 64, 64" ShadowOffset="2">
            <points>
                <asp:DataPoint YValues="6" />

With this method, you’re basically telling the chart that you’d like it to return a Binary Stream (surprise). In essence, the content of the server’s response will be the string representation of the binary object which your browser will render as an image. In a sense, it’s similar to making a request directly to ChartImg.axd directly. The difference here is you’re creating the binary representation of the chart from memory rather than a physical location on disk.

Both of these methods are very easy to set-up and require little to no-thought. I have to admit using a temporary directory feels a little icky but that may just be my OCD kicking in.

There’s another way, though.

If for some reason these two methods don’t jive with you, though, there is another way. It’s sort of hacky – but it works. Basically, you can convert a binary stream to Base64 and return the string directly to the image tag.

<img src='data:image/png;base64, iVBORw0KGgoAAAA[snip]; />
That means that you can generate your chart entirely in a codebehind and then just return the string via an AJAX request.
//Generate your chart
System.Web.UI.DataVisualization.Charting.Chart Chart1 = new System.Web.UI.DataVisualization.Charting.Chart();
//Save it to a stream and return it
System.IO.MemoryStream imageStream = new System.IO.MemoryStream();
Chart1.SaveImage(imageStream, ChartImageFormat.Png);
return Convert.ToBase64String(imageStream.ToArray());

All in all the, binary streaming or the Temp Directory method for chart rendering will probably satisfy your requirements 80% of the time.  It would be interesting to see how each of these scale/perform in a heavily loaded environment.  Hopefully, this provided you with a sufficient high-level overview of your chart rendering options. 

Share this post :

Remotely Enabling Remote Desktop from the Command Line

Okay, this is a very easy find if you search for it…but also very handy (Thank you My Digital Life).  Save as a CMD file and use as directed…

@echo off
@echo Remote RDP Enable Script by My Digital Life
@echo -------------------------------------------
@echo.
setlocal
if {%1}=={} goto syntax
:loop
if {%1}=={} goto finish
set remote="\\%1\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server"
shift
reg.exe ADD %remote% /v fDenyTSConnections /t REG_DWORD /d 0 /f>;nul 2>&1
if NOT %ERRORLEVEL% EQU 0 @echo %remote% NOT found.
goto loop
:syntax
@echo No computer name or host name specified.
@echo.
@echo Syntax: RemoteDesktop Computer1 [Computer2 .... Computern]
goto loop
:finish
endlocal

Share this post :

 

Technorati Tags:

Very Impatient & Moderately Lazy: Shortcuts

Very impatient, moderately lazy;  I use the keyboard to do whatever I can whether I’m in Visual Studio, navigating the web, or just moving around the O/S.  For example, if I need to  launch word I’m just going to hit the Windows Key + R and then type WinWord.  I use that technique for basically anything I know the application name for…notepad, calc, whatever.  If the application name is “too much” for me to type I’ll create a real old-skool bat file and throw it into my C:/Windows/System32/ folder.  A few of the handy ones that I use lately are the following…

REM Clear cache in IE
start "" "RunDll32.exe" InetCpl.cpl,ClearMyTracksByProcess 8
exit
REM Google something on a new FF tab
REM usage example: g "C# Generics"
echo off
start "" "C:\Program Files\Mozilla Firefox\firefox.exe" http://www.google.com/search?q=%1
exit
REM Launch VS2008
echo off
start "" "C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe" /nosplash"
exit

It’s not exactly rocket-science but it works pretty well.

Share this post :

 

Technorati Tags:

Learning doesn’t work if you don’t do it right…

So...there isn't really any denying that there is a lot to learn.  New releases from MS, new tools from third-party provides, new libraries..whatever it may be.  It's pretty unrealistic, at least with my current brain, to be able to learn all of that stuff while still having any kind of a life.  Sure, I squeeze in a book on the subway, and my idea of goofing-off at work is going to DotNetKicks.com and checking out what's late and great in .NET today.  That all said, I suspect it may be at least as important to learn how to learn as it is to do your reading and experimenting ("Do the learning" so to speak).  That sounds sort of silly and obvious to some extent, I'm sure, but it may be worth thinking about for a few minutes.  Also, this is a topic that there is considerable about of information on…an easy search* of “how to learn” gets you 365,000 results.  This is only the 4th result and it already has some fantastic insightful ideas…

The Rev. Charles Lutwidge Dodgson (1832-98) wrote under the pseudoym Lewis Carroll, and is primarily known for Alice in Wonderland and Through the Looking Glass. Carroll was a mathematician, photographer, inventor of puzzles and games, and wrote light verse. When he wrote on mathematics and logic it was not without whimsy, as evidenced by the following introduction to his book on Symbolic Logic. In any case, this is excellent advice on how to read any textbook.]

[snip]

  1. Begin at the beginning, and do not allow yourself to gratify mere idle curiosity by dipping into the book, here and there. This would very likely lead to your throwing it aside, with the remark `This is much too hard for me!', and thus losing the chance of adding a very large item to your stock of mental delights . . .
  2. Don't begin any fresh Chapter, or Section, until you are certain that you thoroughly understand the whole book up to that point and that you have worked, correctly, most if not all of the examples which have been set . . . Otherwise, you will find your state of puzzlement get worse and worse as you proceed till you give up the whole thing in utter disgust.
  3. When you come to a passage you don't understand, read it again: if you still don't understand it, read it again: if you fail, even after three readings, very likely your brain is getting a little tired In that case, put the book away, and take to other occupations, and next day, when you come to it fresh, you will very likely find that it is quite easy.
  4. If possible, find some genial friend, who will read the book along with you, and will talk over the difficulties with you. Talking is a wonderful smoother-over of difficulties. When I come upon anything—in Logic or in any other hard subject—that entirely puzzles me, I find it a capital plan to talk it over, aloud, even when I am all alone. One can explain things so clearly to one's self! And then you know, one is so patient with one's self: one never gets irritated at one's own stupidity!

As the excerpt mentions these are suggestions for text-books…so you could easily draw a parallel to reading a technical book (as opposed to a blog, or article).  In that context and in my opinion – these suggestions are spot-on. 

My bottom line: if you’re going to put forth the effort learning, you should learn how to do it right.

*I have no qualms with google but I’m trying to get out of the habit of using the term “google” as if it is a synonym for “search”

Share this post :

Technorati Tags: ,

FireFox Plugins/Addons for Development

Over on InstantShift.com Dkumar M has put together a great list of FireFox add-ons.  The add-on range from web-page eyedroppers [link] to tools that will let you get screenshots of your page in IE from FF [link].  Naturally since I have zero artisitic capability, I gravitated towards the the add-ons that were code-centric.  The most notable add-ons are listed below.  Check out the article [link] and other useful articles by Dkumar M [link].

Name Description
ColorZilla Bottom line: This allows you to grab a hex color-code from any element on a web-page.  It also has functionality built-in for measuring distances within a web-page and some other stuff.
Palette Grabber Creates palettes from web-sites (perhaps from CSS) and outputs a file readable by Photoshop, Gimp, and others.
JSView Allows you to view source on JavaScript files that are referenced on a page without having to type in the URL.
JavaScript Debugger The name of this should be pretty self-explanatory.  Some say this conflicts with FireBug, so watch out for that.

 

Enjoy.

Share this post :

"The type or namespace name 'HttpContextBase' could not be found"

I will never remember this lives in System.Web.Abstractions.

That is all.

What Tools Do You Install On a New Machine?

I recently switched gigs at work and I’ve had re-install, well, all the tools and gadgets that I tend to use.  I’ve also seen a bunch of blog posts lately about tools and plug-ins and I love learning what tools are being out there that I can use…SO, I’ve put together a real short and sweet list myself.  This is by no means exhaustive!

Tool Description
Windows Live I switched over some time ago.  This is a great tool for blog posts.  I also love the code snippet plug-in.
CopySourceAsHtml Handy plug-in for VS2005/VS2008 that allows you to copy code directly to HTML.  This is great for sending code snippets via e-mails and keeping color, formatting, line-numbers, etc.
Command Prompt Here There are tools that do this, but the truth is you really don’t need to download anything for this.  Basically you can add a right-click menu item to windows explorer that will let you launch a command prompt in whatever folder you’ve highlighted.  It’s not rocket science but it is handy.
Reflector If you saw this and thought either “I have never heard of that” OR "Why does everyone always mention this one?” go download it right now. 
FireBug/Windows Dev Toolbar I know some are crazy into one of these two.  I tend to have both installed since some things are easier to do in one over the other.  You can do things like substitute POST/GET values to a server using FireBug but I tend to use BurpSuite or Fiddler2 for that.
HttpFox/WireShark If you’re a web developer, at some point you’re going to need to look at the HTTP traffic.  I used to use HTTPWatch for IE – which I actually like a bit better than HttpFox…but you also have to pay for it.  SO…here I am with HttpFox for my lightweight traffic-snooping.  If things get serious I use WireShark which gives you a much more robust set of functionality (such as right-clicking to view a communications stream between a single requestor/responder rather than sift through everything).  It also does custom color coding and provides a quick, code-like interface for doing filtering.  For example, rather than clicking through a whole bunch of, well, crap, I can type this into a filter-box: ip.src >= 192.168.4.100 && ip.src <= 192.168.4.110 to look at specific range of source IPs. 
FooBar I used to use WinAmp for listening to music.  Foobar is much more lightweight, though, and WAY more customizable.  It also has a bunch of plug-ins and APIs if you get bored.
Diigo [Social Bookmarking] Let me begin this by saying I have no stake in, or association with the creators of Diigo… 

That said, This is by far my most useful tool for information searching.  I try to do at least one hour of research a day on the web about development…sometimes much more.  So I tend to come across a lot of information that is either immediately valuable or will likely be valuable to me in the future.  So, not surprisingly, I bookmark it to a social bookmarking service.  The kicker here is the Diigo will save my bookmarks even if the page goes offline in its local repository.  The second kicker is that I can keyword search all the content in my bookmarks to find anything I’ve bookmarked.  Lastly, I can highlight lines within a page that are of particular interest to me – and even send those to others or post them to the blog.  Seriously, it’s great. 
Additions [6/2/2009] …I decided to keep this list updated
Notepad++ It’s always handy to have a lightweight text-editor around.  This one happens to do syntax highlighting for a bunch of languages out of the box.  It also does user defined syntax highlighting. 
Google Calendar Sync [Info] If you don’t happen to have a smart-phone/blackberry, you can use this free tool to keep your Outlook calendar synched with your Google calendar.  Then you can easily set up SMS alerts and get a reminder for that 3:30 meeting on your mobile – just like you would if you had a blackberry.
GIMP Bottom-line, Photoshop is expensive and this works just as well for my purposes.
SourceMonitor This [free] tool is handy for doing quick code analysis.  It will tell you the number of lines, method complexity (per the definition in Code Complete) and a few other stats. 
WinMerge Tool for doing side-by-side comparisons of files.  It also gives you a great “zoomed-out"
Update [6/4/2009] For FireFox, development associated add-ins, go to this post.

Share this post :

 

Technorati Tags:

Pandora Time Out Annoyances? The 1991-style workaround.

I usually don’t stray off the .NET path too much but…I listen to Pandora a lot.  I also happen to be a nutcase that listens to music throughout the entire night.  Well, if you ever listen to Pandora you know that after an hour it times out…and that can be pretty damn annoying even if all you have to do is go find the tab within FireFox that Pandora is living in and click a button.

In any case, I created a really old-skool workaround for this.  There are probably 900 ways to do this (another one that comes to mind that is probably easier is just using a META-REFRESH)…all I did was create a local HTML document with a frame src=”pandora.com” and a JavaScript SetTimeOut function call.  Basically, it will refresh the page after 60 minutes.  Just copy and paste the code below, call it something.html (Ex: Pandora.html) and double-click.  After an hour, it will refresh…the end.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
   "http://www.w3.org/TR/html4/frameset.dtd">
<HTML>
<HEAD>
<TITLE></TITLE>
<script type="text/JavaScript">
   1:  
   2: <!--
   3: function timedRefresh(timeoutPeriod) {
   4:     setTimeout("location.reload(true);",timeoutPeriod);
   5: }
   6: //   -->
</script>
</HEAD>
<!--
3600000 = 60 min in milliseconds    
 --> 
<FRAMESET cols="99%, 1%" onload="timedRefresh(3600000);">
  <FRAMESET rows="500, 1">
      <FRAME src="http://pandora.com/">
  </FRAMESET>
</FRAMESET>
</HTML>

Share this post :

 

Wolfram Alpha “Search Engine” Goes Live @ 5PM [PST]

One of my last big project revolved around keyword based searching using a Google Search Appliance and an open-source API code the Google Search Appliance written in .NET [link].  Ever since then I’ve been intrigued by keyword search technologies, specifically as it relates to their backend logic.  That all said, Google searching simply matches for strings with a few exceptions.

The guys who developed Mathmetica, though, have developed a processing engine that actually finds answers.  By that, I mean that you can actually find the answer to a question regardless if there is a string based match somewhere on the Interweb.  It’s actually pretty amazing and exposes where the next level of search may go.  For those of you familiar with the Semantic Web, this is sort of like the Semantic Web on steroids. 

In any case, the search engine is supposed to go live this evening at 5 PM…the link is http://www.wolframalpha.com/index.html

There has been a good bit of chatter on this on Gizmodo, and Lifehacker amongst other places.

A live demo is available here.

Using Forms Authentication with HTML Pages (or, really, any file-type you desire)

So, I recently had to write a small application that would basically prevent anonyomous users from accessing a site...which normally would take all of 5 minutes.  The catch, though, was that the site I had to prevent access to was static content...predominantly HTML and Flash movies.  Setting up forms authentication at first glance seems to work without issue...until you try to access an HTML file directly.  Upon doing so, you'll go to the HTML page without issue for the simple fact that HTML pages aren't pushed through the ASPX pipeline which prevents HTTP requests from being intercepted and redirected to what would be a login page. 

The good news is this is very easy to solve, using the following technique you'll be able to prevent access to any file-type, HTML, JPG, etc.  For the purposes of my instructions I'll assume we're just adding .HTML, but you'll need to modify the extension as it pertains to your file-type.  Please note, I came across the instructions for this here - I decided to put them here for others to leverage...as well as myself when I forget the steps 8 months from now :)

1. Configure forms authentication as you normally would

2. Navigate to the IIS Snap-in and right-click your virtual directory or web-site, and select properties. 

3. Navigate to the "Home Directory" tab within the properties window, and click "Configuration"  At this point, you'll hopefully see something similar to the following:

AppConfig

4.  Not surprisingly, this is where file extensions and handlers are associated.  We'll simply need to add the association between the .HTML extension and the ISAPI. 

5.  First, though, we'll need to grab the path for the ISAPI filter we want to use.  I think the path is probably standard depending on what framework you're using, but to stay on the safe side scroll to the .aspx file extension in the "Application Extensions" listing.  Once you find it, either double-click it or highlight it and click "Edit".  You'll see a window that resembles the following:

IsapiProps

6.  All we need to do here is copy some information.  Go ahead and launch notepad or your preferred text editor.  Copy the full path to the aspnet_isapi.dll and copy the verbs in the "Limit to:" text-field.  In this case, that'll be GET,HEAD,POST,DEBUG.  After you grab that information, cancel out of this window.

7.  You should be back at the "Application Configuration" screen.  Go ahead and click "Add".  The add button will launch a window identical to the window above.  You just need to populate it by copying and pasting in the path to the aspnet_isapi.dll and the verbs in the "Limit to:" text-box.  Basically, it should look identical to the following:

HtmlProps

8.  That should do it for the IIS portion.  Now, all you need to do to take advantage of this set-up is modify your web.config by adding these lines the following.  In the httpHandlers section add:

<httpHandlers>

<!-- other verbs removed to stay concise -->

<add verb="GET, HEAD, POST, DEBUG" path="*.html" type="System.Web.UI.PageHandlerFactory"/>

</httpHandlers>

9.  Last step...add the following to the web.config within the compilation section...

<buildProviders>
   <add extension=".html" type="System.Web.Compilation.PageBuildProvider" />

</buildProviders>

10.  In theory, you're done.  You'll need to do the same type of thing with the other extensions you'd like to do this with (that means one for .htm, too). Also, you may want to think about doing this for things like images, CSS, etc. 

Enjoy...

Another Abstract Factory & Strategy Pattern Explanation

Alright, I already know what you're thinking after reading the title, but that's why I prefaced it with "Another..." Long story short, I wrote this nice long e-mail to my friend/colleague here at work and I thought maybe it would be of use to one of the three people out there that haven't read 84 different explanations of the abstract factory pattern. Again, it was formally an e-mail so I ran through it and added some clarifications in brackets...hope I made _some_ sense :) A link to an explanation of the abstract factory pattern is here: http://69.10.233.10/KB/cs/Abstract_Factory_Pattern.aspx but IMO this stuff makes a lot more stuff in context. I tend to use this pattern a lot, but [to me] it seems to make a lot of sense when dealing with security/roles - it's an easy way to accommodate adding roles without having to go everywhere in your application and modifying code..but it can definitely be used elsewhere (I use it in JavaScript a lot too) Basically just create an interface with the method signatures you want to implement.

Public Interface ISecurityCheck
       Function canEditProfile(ByRef UserInfo As Object, ByVal ProfileID As String) As Boolean
       Function isAuthorizedPage(ByVal PageId As Integer, ByVal UserInfo As Object) As Boolean
  End Interface

Then, all you have to do is create a class for each role in your application. The class will implement the interface iSecurityCheck...This is what the implementation looks like for anonymous users in [my latest application]. Basically, anonymous users can read everything in [the application] but not write anything.

 

Public Class AnonymousSecurityCheck
       Inherits SecurityBase
       Implements ISecurityCheck
   
       Public Function canEditProfile(ByRef UserInfo As Object, ByVal ProfileID As String) As Boolean Implements ISecurityCheck.canEditProfile
           Return False
       End Function
   
       Public Function isAuthorizedPage(ByVal PageId As Integer, ByVal UserInfo As Object) As Boolean Implements ISecurityCheck.isAuthorizedPage
           Return isPageAllowed(PageId, UserInfo)
       End Function
   
  End Class

CanEditProfile takes a UserInfo object as a parameter which is basically my user object. There are a few propreties in UserInfo, but the most important ones are ProfileID and Role. CanEditProfile always takes a ProfileID parameter - this should probably be named better, but it is supposed to be the ProfileID of the page you're currently looking at. This allows me to cross-reference the UserInfo.ProfileID property with the ProfileID of the current page. In the case of the anonymous user, it returns false no matter what. isAuthorizedPage basically runs a stored proc to see if the user that is currently logged in can even load/view the page... The implementation of the rest of the roles looks like below, but there really isn't spectacular happening. Basically if you're a normal user, I return true for CanEditProfile assuming your UserInfo.ProfileID and the ProfileID of the page you're looking at is the same. isAuthorizedPage always runs the same stored proc (But the implementation could easily change) Admins can basically do whatever they want...so this always returns true for both functions:

Public Class AdministratorSecurityCheck
     Inherits SecurityBase
     Implements ISecurityCheck
 
     Public Function canEditProfile(ByRef UserInfo As Object, ByVal ProfileID As String) As Boolean Implements ISecurityCheck.canEditProfile
         Return True
     End Function
 
  
     Public Function isAuthorizedPage(ByVal PageId As Integer, ByVal UserInfo As Object) As Boolean Implements ISecurityCheck.isAuthorizedPage
         Return True
     End Function
 
End Class
 
 'CanEditProfile returns true only if the ProfileID = UserInfo.EmployeeID
 
blic Class UserSecurityCheck
     Inherits SecurityBase
     Implements ISecurityCheck
 
     Public Function canEditProfile(ByRef UserInfo As Object, ByVal ProfileID As String) As Boolean Implements ISecurityCheck.canEditProfile
         If TypeOf (UserInfo) Is AppMembershipUser Then
             If UserInfo.ProfileID.ToString = ProfileID Then Return True
 
         End If
         Return False
     End Function
 
  
     Public Function isAuthorizedPage(ByVal PageId As Integer, ByVal UserInfo As Object) As Boolean Implements ISecurityCheck.isAuthorizedPage
         Return isPageAllowed(PageId, UserInfo)
     End Function
 
 End Class

 

So that's all relatively straight forward. The best part of this is that you can add more roles, or change the business rules without a lot of work. So within a page, you use this like this: Dim isec As ISecurityCheck = AuthorizationFactory.GetAuthorization(UserInfo) CanEditProfile = isec.canEditProfile(Me.UserInfo, currentPageProfileId) So I get the true/false value telling me whether a user can edit a profile regardless of how many roles exist or whether I add or remove roles. Since you're running the CanEditProfile method yourself above which returns a value of type ISecurityCheck, this all works.

Public Class AuthorizationFactory
      Public Shared Function GetAuthorization(ByVal UserInfo As Object) As ISecurityCheck
  
          If TypeOf (UserInfo) Is AppMembershipUser Then
              UserInfo = CType(UserInfo, AppMembershipUser)
              With UserInfo
                  If Common.stringIsInArrayList(Constants.ROLE_ADMINISTRATOR, .rolename) Then Return New AdministratorSecurityCheck
                  If Common.stringIsInArrayList(Constants.ROLE_USER, .rolename) Then Return New UserSecurityCheck
             End With
         End If
 
         Return New AnonymousSecurityCheck
     End Function
 End Class

Hmm. This might be the longest e-mail I've written in a long time...Hope I did a decent job of explaining, though

iHttpHandler vs iHttpAsyncHandler

I have been playing with both the iHttpHandler and iHttpAsyncHandler lately, and I came across some interesting information.  There are a couple of blog posts out there explaining when to use one over the other (see Mads Kristensen's post here, or Vlad Hrybok's post here)

So when does it make sense to use Async?

Consensus seems to be that it makes sense to use the iHttpAsyncHandler for long running operations, so while it probably doesn't make sense to use an iHttpAsyncHandler for say, loading images, it probably does for having a web-service perform some [relatively] processor intensive work. In my case, I considering using the Async handler for generating XML that is fed to a flash movie.  Still, there was a potential can of worms here.  Per this MSDN article from Fritz Onion...

"There is one remaining problem with this asynchronous handler implementation—it has the potential to create an unbounded number of threads. If a large number of requests are made to the asynchronous handler, all of which take a significant amount of time to service, then you could easily end up creating more threads than the underlying operating system can handle..."

Fritz goes onto state that....

"Building asynchronous handlers to service CPU-intensive requests only adds threads to compete with the ASP.NET thread pool threads and may actually slow down the overall processing time for the request."

The moral of the story, don't use AsyncHandlers because they *sound* like they'll give you a performance boost.  Application of the Async handler should be thoughtful and empirically driven.  That said, Fritz does provide a link to a ThreadPool library that Mike Woodring developed, DeveloperMentor, (link here), should you want to take full advantage of Asynchronous capabilities in a thread-safe manner.

You'd think after all that warning I wouldn't provide the code to create/implement an iHttpAsyncHandler, but since I couldn't find VB.NET code too easily, I figured I'd provide it here.

 
Public Class MyAsyncExample
Implements IHttpAsyncHandler
' You'll need this to read from session
' Implements IReadOnlySessionState 
' You'll need this to read/write from session
' Implements IRequiresSessionState
 
    Private AsyncTask As AsyncTaskDelegate
    Protected Delegate Sub AsyncTaskDelegate(ByVal context As HttpContext)
    
    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpAsyncHandler.ProcessRequest
    'Do what you need 
    End Sub
    
    Public Function BeginProcessRequest(ByVal context As HttpContext,ByVal callback As AsyncCallback, ByVal extraData As Object) _
        as IAsyncResult Implements IHttpAsyncHandler.BeginProcessRequest
        
        Me.AsyncTask = new AsyncTaskDelegate(Addressof ProcessRequest)
        Return AsyncTask.BeginInvoke(context,callback,extraData)
    End Function
    
    Public Sub EndProcessRequest(ByVal ar As IAsyncResult) Implements IHttpAsyncHandler.EndProcessRequest
        Me.AsyncTask.EndInvoke(ar)
    End Sub
    
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpAsyncHandler.IsReusable
        Get
            Return False
        End Get
    End Property
 
End Class

If you're looking for more information the MSDN link to Fritz's article, though far from new, is a great place to start.

Enjoy

Useful Links [Random Code Examples and A Memory Management Article]

Came across some links doing my daily research that I believe others would find useful.

Mike Woodring has a rather large list of code-examples on everything from remoting and sockets to HTTP Logging modules.  It's a really great resource and cruising through this code was definitely a learning experience for me - the more I learn the less I know about before :)

Link number two is a refresher on memory management in the .NET framework.  I find it's easy to plug-away developing ASP.NET (And maybe even WinForms apps) without *really* comprehending the way memory is allocated to the various object/data-types available in the framework.  I've also been doing some reading on C++ lately, so memory management is one of my new areas-of-interest.  Nonetheless, this article is a good read.

Cheers.

Dynamic Image Loading, Caching, & Performance

I came across an interesting blog posting and comment today doing some research on ASP.NET performance.  Essentially, Alik Levin mentions that if you're loading images dynamically (either from a file-system or DB) you will not be taking advantage of browser/client caching out-of-the-box.  I'm using a very simple HTTP Handler in one of my applications, the handler, well, handles serving up images in my application - something there are lots of.  So it seems like it makes a lot of sense to have the browser handle caching of these images.

The source code for my entire HTTP Handler looks like this (sorry C# folks):

<%@ WebHandler Language="VB" Class="Image" %>
Imports System
Imports System.Web
Imports System.Web.HttpRequest
 
Public Class Image : Implements IHttpHandler  
 
    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        Dim empID As Integer = Decrypt(Request.QueryString, "EmployeeID")
        If (empID = Nothing) Then Return
       
        Dim Photo As Employee.EmpPhoto
        Photo = Employee.GetPhotoByEmployeeID(empID) 
        
        With EmployeePhoto
            context.Response.ContentType = .ContentType
            context.Response.BinaryWrite(.Data)
        End With
    End Sub
 
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property
 
End Class

Christopher Lewis mentioned that you can easily add the appropriate cache header to your server's response by a few lines of code to your logic.  Complete code below with comments, note lines 17-27...

   1: <%@ WebHandler Language="VB" Class="Image" %>
   2: Imports System
   3: Imports System.Web
   4: Imports System.Web.HttpRequest
   5:  
   6: Public Class Image : Implements IHttpHandler  
   7:  
   8:     Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
   9:         Dim empID As Integer = Decrypt(Request.QueryString, "EmployeeID")
  10:         If (empID = Nothing) Then Return
  11:        
  12:         Dim Photo As Employee.EmpPhoto
  13:         Photo = Employee.GetPhotoByEmployeeID(empID) 
  14:         
  15:         With EmployeePhoto
  16:             context.Response.ContentType = .ContentType
  17:             'Add below lines to set cache header per Christopher's suggestions
  18:             context.Response.AddFileDependency(imageFileName)
  19:             context.Response.Cache.SetETagFromFileDependencies()
  20:             context.Response.Cache.SetLastModifiedFromFileDependencies()
  21:             context.Response.Cache.SetCacheability(HttpCacheability.[Public])
  22:             context.Response.Cache.SetExpires(DateTime.Now.AddTicks(600))
  23:             context.Response.Cache.SetMaxAge(999)
  24:             context.Response.Cache.SetSlidingExpiration(True)
  25:             context.Response.Cache.SetValidUntilExpires(True)
  26:             context.Response.Cache.VaryByParams("*") = True
  27:             'End added lines
  28:             context.Response.BinaryWrite(.Data)
  29:         End With
  30:     End Sub
  31:  
  32:     Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
  33:         Get
  34:             Return False
  35:         End Get
  36:     End Property
  37:  
  38: End Class

Learn somethin' new everyday :)

Technorati Tags: ,

ASP.NET Performance Tips

In the post below I am going to run down a short-list of some of the less-popular performance tips and the reasoning behind them.  There are loads of blog postings and articles on asp.net performance enhancements, and I urge you to check those out as well.  Onto the good stuff...

Session.ReadWrite versus Session.ReadOnly

It goes without saying that using the Session object will incur some performance overhead so if possible it should be turned off in the web.config.
That said, If you’re using the Session object to maintain session in your application...
Ensure Session.ReadOnly is true rather than using Session.ReadWrite across the application.  There is more information in the link below, however the short story is there is no ReadWriterLock done if Session.ReadOnly = true.  From this MSDN link, “ReaderWriterLock allows multiple threads to read a resource concurrently, but requires a thread to wait for an exclusive lock in order to write to the resource.”  This will make a fairly significant difference if sessions are being managed in a state database, in which case only one-trip to the database is made when using ReadOnly, rather than two while using ReadWrite...which leads me to...

Optimizing your Session when using Out-Of-Process (E.g., State Server or State Database) Session Management

When using out-of-process session management methods objects must be serialized on their way into the state server or state database.  Naturally, this means the data within the session object must be deserialized on the way back out [to the application].  In order for this to work you'll need to add the [Serializable] attribute to the beginning of the class that needs to go into the session object.  For example...

[Serializable]
public class User{
    public string firstName; //Small text field
    public string lastName; //Another small text field
    public string usersLifeStory; //Is a large text field
}

As you may infer from my not-so-clever comments, there may be a problem with this.  Let's say the user object needs to be stored in my session object [and therefore needs to be serializable], but there are some large, or otherwise inefficient fields in this object (such as non-primitive types).  For the purposes of this example, let's also say that I don't need to store my user's life story in my session object because it's only displayed on one page where I can pull it from the application's database.  The .NET framework makes it very easy to exclude properties within my object from being serialized.  In fact, it's as easy as adding a few more attributes. 

[Serializable]
public class User{
    public string firstName; //Small text field
    public string lastName; //Another small text field
    [NonSerialized]  //Prevents usersLifeStory from being serialized
    public string usersLifeStory; //Is a large text field
}
Easy peasy.  Note that this means the "usersLifeStory" variable will not be accessible via the session object, of course.

Cache and...

think about your caching strategy before you go developing pages or user controls willy nilly.  This will make using the .NET frameworks caching features much easier and will hopefully prevent you from having to make some logic work differently just so you can cache...this will make life especially easy when using features like output cache substitution and creating methods/strategies for querying your DB.  Again, caching is something you should be thinking about before you launch your IDE.

There are tons of resources for learning about output caching, data caching, and the other features the .NET framework provides, so I'm going to skip that.  I am, however, going to mention a really easy way to automagically cache return values from WebMethods/Web-services because I don't see it mentioned very much. 

public class ExampleService{
    //The cache duration attribute handles ALL caching for you
    
    [System.Web.Services.WebMethod(CacheDuration=60)]
    public string GetSomethingFromSomewhere(){
        //Logic to get some data from a data-source
    }
}

That's it...Just add the CacheDuration attribute and you're good to go.

Update [1/5/2009]: Scott Mitchell has just posted a great, and concise article on per-request-caching.  This is easy-to-use and powerful functionality.  Read the article here.

Use HTTP Compression!!!

Maybe it's the luck of the draw here, but in my experiences most developers/sys admins/etc for some reason or another don't enable HTTP Compression, either deflate or GZIP.  I'm sure there are some legitimate reasons for not enabling this functionality for some applications, but everyone else should absolutely have it turned on.  Yes, it's going to cost some CPU but you can play with the settings.  Bottom line is you will see a dramatic difference in page response times.  Keep in mind you can configure HTTP Compression to compress a number of file-types, including CSS/JS/HTML/ASPX/ASMX/ASHX etc. 

Also, I came across this post doing some research the other night - looks like Mads did some testing on GZIP versus Deflate.  The results are interesting...I have yet to do some testing on my end.

For some reason or another the IIS6 team didn't give us an GUI to turn on/off HTTP Compression, so you need to go into the metabase.  It's really only confusing the first time you do it.  There are a number of good tutorials on the web.  I think this is the one I used.  You'll probably want to ensure HTTP Compression is on by using a tool like HTTPWatch, or its FireFox equal...the name of which currently slips my mind.  Google is your friend :)

Be careful with the App_Themes folder!

I don't have any screen shots handy, and I'm not at my office so you're going to have to trust me on this but...Be careful what you put into app_themes.  No matter what you reference in your pages using the <style> tag, ASP.NET/VS is going to load all the style-sheets you have in app_themes.  This means if you're using a very specific style-sheet on one page (say, for a prototype, jQuery, or script.alicio.us library) that the JavaScript is going to get loaded every.single.time.   So, just to be clear here, no matter what you do, VS is going include all the CSS (or other) files you have in your app_themes folder.  Best idea IMHO is to use this strictly, well, for your themes and create another folder for your CSS, and another for your scripts.  Just don't use app_themes as your miscellaneous include folder.

Be careful how you populate objects!

Okay, I'm sliding this one in as a general tip just because it's a bug I discovered in some code I was going through.  Okay, it *may* have been my code, but no one can prove anything.  In any case, I was populating an object and calling a second method within the context of a USING block.

public Employee GetEmployee(int EmpId){
    using (Connection)
    {
        SqlDataReader dr = SqlHelper.ExecuteReader(Connection, CommandType.StoredProcedure, "GetUser", New SqlParameter("@ID",EmpId);
        _firstName = dr[0];
        _lastName = dr[1];
        _photo = GetEmpPhoto(EmpId);
    }
}
 
public byte[] GetEmpPhoto(int EmpId){
   using (Connection)
   {
       return SqlHelper.ExecuteReader(Connection, CommandType.StoredProcedure, "GetPhoto", New SqlParameter("@ID",EmpId);
   }
 
}

What happens in the above scenario?  I'll give you a hint, it's not good.  The call to GetEmpPhoto() in the GetEmployee() method spawns a new connection to the database within the GetEmpPhoto() method.  The problem is the connection spawned within GetEmpPhoto() never gets closed (or returned to the pool).  This is probably a pretty subjective case, but in any case doing stuff like this is basically asking for trouble.

There are probably an infinite number of applications tweaks to increase performance, including some of the more popular ones listed below that you can easily Google and find information on.  In this entry I've tried to explain some of the lesser-known/lesser-implemented tips I found useful.  Be sure to get the following items out of the way when you're looking for performance gains.

- Disable viewstate (In web.config or on a control-by-control basis.  Don't forget about control-state).   Also, be sure not to store any non-primitive types in viewState as you'll big a large price in terms of performance.  I have seen some suggestions on forums informing people to use the session object, instead.  I'd be wary of this as well.

- Set debug="false"  This shouldn't need much explanation.

- Check for isPostBack, and isCallBack in page.Load() to avoid re-loading unnecessarily

- Minify CSS/JS

- Compress images

- Use AJAX not only when convenient, but when it will enhance performance

Omar Al Zabir does a pretty good job of explaining some of these items.  I would check out this article on codeProject and his blog for info on the above or just do some googling.

Hope this helped!

Sanjay

kick it on DotNetKicks.com
Twitter