Tuesday, February 17, 2009

Removing the leading blank in ASP.Net pages

Professional web developers have long been placing doctype declarations at the beginning of their HTML and XHTML. ASP.Net has posed a special challenge due to the need to place @Page, @Register, and other directives at the beginning of the pages. This typically renders on the browser as a newline with the doctype declaration placed on line 2. The simplest solution I've found to this is to put <% %> at the beginning of your doctype line.

The ASP.Net page generating system removes newlines between directives, leaving only the one pushing down your doctype. By putting in the server side code markers and not following them with a newline before your doctype, the system does its usual newline removal and immediately begins rendering after the closing marker.

Thursday, February 5, 2009

Human Alphabetizing

Dave Koelle has posted an algorithm that sorts information the way a person would, putting x2 before x100 and abc456 after abc97. He even has it coded in C++, C#, Groovy, Java, JavaScript, Lua, OCaml, Perl, PHP, Python, Ruby. It's licensed under the LGPL, so no licensing fees to fear.

Thursday, January 29, 2009

Adobe Flex 3 Installation and First Impressions

If I hadn't just done it, I wouldn't believe it. I never so much as considered what made Flash files work before Tuesday. In two days, I went from knowing nothing about Flash programming to having a fully functional SOAP client written using Flex 3. And I didn't spend a dime on it yet. I haven't received my book on Flash programming yet. Just went by some online help and sample code sites. If you need Flash for a utility purpose and not for making interactive movies, FlashDevelop is fantastic for the job and it's free. I already had Java 1.6 and DotNet 2.0 installed, so I just had to unzip the free Adobe Flex SDK and tell FlashDevelop where I installed it.

Writing in Flex 3 is a lot like writing XHTML and JavaScript in that Flex 3 is XML based and the tags have properties very similar to XHTML and CSS properties. The accompanying ActionScript can be incorporated into the Flex 3 file using <mx:script> and CDATA or stored separately in an AS3 file, just like in-line vs external JavaScript.

As for the SOAP part of things, IBM has a great example of SOAP Client creation, but it shows lots of how without explaining why. Be prepared to experiment a lot.

Adobe does have a good deal of help available on their site, but all I've found so far are along the lines of platform references with little reference to the basics of the ActionScript language. It's probably there and I just haven't found the write help docs yet.

Tuesday, January 27, 2009

New Blog Home

While Wordpress is a great piece of blogging software, I found their free hosting service too restrictive for my needs (not complaining, just growing). Thought I'd give Blogger a try as it supports Javascript and template editing without having to pay extra for it. Found a great Wordpress2Blogger conversion utility that moved over all my articles and posted comments. Ignore what it says about a WXR export, the XML file from Wordpress worked just fine. Looks like the site links got the ax though. Won't take long to recreate that. The recommended reading page appears to be toast as well.

Thursday, January 22, 2009

HowtoForge: Setting and Changing MySQL Root Password

Great article on HowtoForge on dealing with how to recover from forgetting MySQL's root password (which I admit I did a few years back on a server I had set up years before even that). Having this article back then would have saved me a lot of searching.

VB-like language for QT (KDE/Linux) developers

Named KBasic, it's been developed for the QT library, making it viable for cross-platform programming. If you're a VB programmer who's been wanting to try your craft on a Linux system, but couldn't or wouldn't learn a new language, you should probably give it a try. It even includes SQLite for rapid file-based database development. It understands the syntax of both VB6 and VB.Net as well as the old MSDOS QBasic / QuickBASIC.

Any current ET(SS) in the Navy want to see if TTYTalk still works? :)

Friday, January 16, 2009

Safely Retrieving Values In ASP.Net 2.0

This is an update of Getting a number in an ASPX script. String cleansing has been added so you don't accidentally try to perform string manipulations on null values.
public static class InputCleaners {
public static string CString(object Value) {
return (Value as string ?? "");
}
public static int CInt(object Value) {
int Result;
if (!int.TryParse(CString(Value).Trim(), out Result)) { Result = 0; }
return Result;
}
public static long CLng(object Value) {
long Result;
if (!long.TryParse(CString(Value).Trim(), out Result)) { Result = 0; }
return Result;
}
public static float CFlt(object Value) {
float Result;
if (!float.TryParse(CString(Value).Trim(), out Result)) { Result = 0f; }
return Result;
}
public static double CDbl(object Value) {
double Result;
if (!double.TryParse(CString(Value).Trim(), out Result)) { Result = 0D; }
return Result;
}
}

In your ASP.Net code, you can call it as follows...
int UserSubmittedValue = InputCleaners.CInt(Request["userinput"]);

Bear in mind, this code was written for ASP.Net, not system programs. It's meant for cleaning inputs from the Request collection, which only returns strings and nulls. Calling these routines with a value that's already a different kind of number is likely to return zero. You can, of course, add overrides to these routines to better handle such situations, but that is beyond the scope (ASP.Net) of this article.

Sunday, January 11, 2009

Catching Unwanted Spiders and Bots In ASP.Net 2.0

This is an upgrade of the code previously posted in Catching Unwanted Spiders And Content Scraping Bots In ASP.NET.
To use it, add the following to your code-behind files on the page you've set up to catch the unwanted scrapers...
GrokkingCode.ClientTrap.BadClients.Instance.AddClient();

... and the next line of code gets added on the pages you don't want scraped...
GrokkingCode.ClientTrap.BadClients.Instance.TestClient(false);

... if you don't want to compare the UserAgent and ...
GrokkingCode.ClientTrap.BadClients.Instance.TestClient(true);

... if you do.

Remember to put the bad bot catching page in your robots.txt file so legitimate bots won't try to access it and badly behaved bots will.

The following code is saved as App_Code/BadClients.cs
using System;
using System.Web;
using System.Web.Caching;
using System.Collections.Generic;

namespace GrokkingCode.ClientTrap {
/// <summary>
/// Handle clients forbidden from accessing site
/// </summary>
public sealed class BadClients {
private HttpContext http = null;
private Dictionary<string, string> dictBadClients = null;
private string sUserIP = "";

public static BadClients Instance {
get {
try { return (HttpContext.Current.Items["oBadClients"] ?? (HttpContext.Current.Items["oBadClients"] = new BadClients())) as BadClients; }
catch (Exception ex) { throw new Exception("Failed to instantiate BadClients.", ex); }
}
}

private BadClients() {
http = HttpContext.Current;
sUserIP = http.Request.UserHostAddress;
dictBadClients = http.Cache["badclients"] as Dictionary<string, string>;
if (dictBadClients == null) {
dictBadClients = new Dictionary<string, string>();
http.Cache.Insert("badclients", dictBadClients, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(60), CacheItemPriority.Normal, null);
}
}

public void AddClient() {
if (!dictBadClients.ContainsKey(sUserIP)) {
dictBadClients.Add(sUserIP, http.Request.UserAgent);
}
return;
}

[Obsolete("You should specify a MatchAgent value. The default of true is being used.")]
public void TestClient() {
TestClient(true);
}

public void TestClient(bool MatchAgent) {
if (dictBadClients.ContainsKey(sUserIP)) {
if (!MatchAgent || dictBadClients[sUserIP].Equals(http.Request.UserAgent)) {
http.Trace.Write("Attempting to block client from " + sUserIP);
try { http.Response.Clear(); }
catch { http.Trace.Write("Could not clear response buffer. I suggest you move the TestClient call to earlier in your code."); }
http.Response.End();
}
}
}
}
}

The class is a drop-in replacement for ASP.Net 2.0 users to the ASP.Net 1.1 compatible version. I made the following changes...

  • TestClient() has an optional boolean parameter to ignore the UserAgent sent by the visitor's browser. The default is true to match the previous version's behavior. In the previous version, a bot could evade the block by sending a different UserAgent with each request. Passing false will allow you to block by IP address alone.

  • I've extended the lifespan of the cached entries to 60 minutes.

  • I have removed the unused using statements.

  • The tests for a web environment have been removed as unnecessary overhead. Even a beginning programmer will figure out real fast that this is of no use outside web applications.

  • Reinserting the storage object over itself in the cache has been removed. According to this article on ASP.Net Cache and Session State Storage the object is stored in the cache as a live reference to a real memory location, meaning the call to Dictionary.Add() is updating the object referenced by both the cache object and the dictBadClients variable. The call to Cache.Insert() was redundant.

  • The constructor was changed to remove the check for the cache entry and use Cache.Add() if it wasn't present. Using the C# "as" type casting returns a simple null when the cache entry isn't there and reduces the chances for a race condition between different site visitors. The Cache.Insert() works just as well whether the object already exists in the cache or not.

  • An [Obsolete] directive has been added to the TestClient() without parameters to warn people dropping this in in place of the prior version that they should specify whether or not they want to match UserAgent strings.

Friday, November 21, 2008

FTP using ASP3 and no 3rd party add-ons

CodeToad has an excellent article up on using wscript to perform FTP actions from ASP3 web pages. I could have used this about 3 or 4 years ago before I began moving to ASP.Net. According to the comments listed, there may be difficulties getting this to work. It is possible your hosting service won't have wscript installed due to security reasons, but if they do, this could really save a developer some licensing fees on third party libraries.

Thursday, November 20, 2008

Virtual computing in Ubuntu

Some time back I mentioned the problems I was having with VMWare on one of my Ubuntu systems. I have since scrapped VMWare and switched to Sun's VirtualBox Open Source Edition software instead. It's currently actively maintained by the Ubuntu community. It even has similar integration tools available for the hosted OS so you can move your mouse in and out of the window without any special keystroke gymnastics. It's also insanely easy to switch from using a real CD in the host drive to a CD image stored on your hard drive (like the image for those integration tools) without rebooting or editing any configuration files. And unlike VMWare's free VMPlayer, you don't need to hunt down another piece of software like Qemu to create disk images. VirtualBox has a very thorough wizard for the image creation process.

Testing alternative Linux distributions has never been easier for me.

There's a good help page for VirtualBox at the Community Ubuntu Documentation wiki. I found the system just worked after installing it using Synaptic without a lot of installation steps mentioned in the Wiki although it's possible I've just forgotten performing those steps.