JitBit Software. Net Profile Switch, Macro Recorder, AspNetForum, RSS Feed Creator.
products download purchase support company blog

Dec 20, 2007

Macro Recorder: another trigger example

Another example of "triggering" events with our Macro Recorder software and the IF statement. The following script makes Macro Recorder wait until Notepad window has appeared.

LABEL : start
IF WINDOW EXISTS : *notepad*
GOTO : end
ENDIF
DELAY : 2000
GOTO : start
LABEL : end
MESSAGE BOX : Notepad window found, exiting..

As you can see, this macro checks every 2 seconds, and if it finds a window with the "notepad" text in its caption, the macro exits. Simply save the above text as a plain-text file with a ".mcr" extension and load it into the Macro Recorder to test how it works.

Dec 15, 2007

SEO friendly URLs with ASP.NET

Search engines like human-readable URLs with keywords in it, and hesitate to respect messy URLs with a lot of query-string parameters. So, to make our ASP.NET database-driven website SEO-friendly we have to get rid of our complex URLs.

Example of a "SEO-friendly" URL:
http://www.jitbit.com/mailjet-newsletter-software.aspx

Example of a "SEO-unfriendly" URL:
http://www.jitbit.com/product.aspx?ProductID=18

Solution 1: Fake pages and "Server.Transfer". As you can see the two URLs above point to the same page. Basically it is the same page and it works like this: the page mailjet-newsletter-software.aspx contains no code at all and performs a Server.Transfer (aka server-side redirect) to product.aspx like this:

Server.Transfer("product.aspx?ProductID=18");

That's it. We have one "product.aspx" page which expects a "ProductID" parameter and a lot of "fake pages" with SEO-friendly names like firstproduct.aspx, secondproduct.aspx etc., which simply perform a Server.Transfer to the "product.aspx" with the right ProductID.

Simple, isn't it?

But this solution requires a lot of hard-coding - we will have to create all these fake pages and add a Server.Transfer command. So let's go a little further: we will create one base class for all our "fake pages" and add a record to the "tblProducts" table in the database:

tblProducts
ProductIDProductNameProductPage
1First Productfirstproduct.aspx
2Second Productsecondproduct.aspx
3Third Productthirdproduct.aspx


public class ProductPage : Page
{
private SqlConnection cn;
private SqlCommand cmd;
protected override void OnLoad(EventArgs e)
{
//lets initialize our database connection
//remember to specify the connection string
cn = new SqlConnection(yourConnectionString);
cmd = new SqlCommand();
cmd.Connection = cn;

//determine the page being requested in the browser
string pageFileName = Request.Path.Substring(Request.Path.LastIndexOf("/")+1);

//get the right ProductID from the database
cmd.CommandText = "SELECT ProductID FROM tblProducts WHERE ProductPage=@ProductPage";
cmd.Parameters.AddWithValue("@ProductPage", pageFileName);
cn.Open();
object productID = cmd.ExecuteScalar();
cn.Close();

//if ProductID found
if(productID!=null && productID!=DBNull.Value)
{
//let's transfer the execution
Server.Transfer("product.aspx?ProductID=" + productID.ToString());
}
}
}
Now we have to create our fake pages, inherit them all from the ProductPage class and voi la - that's it! We can also optionally remove all the HTML-code from the aspx-files, leaving the "Page" directive only.

Solution 2: Virtual Pages. This method is pretty similar, except that we don't need to create any pages at all. Instead, we will add an HttpModule, which intercepts HTTP requests, and the user requests a non-existent page, performs a Rewrite operation. First we will create our HttpModule:


namespace URLRewrite
{
public class ProductPageModule : IHttpModule
{
public ProductPageModule()
{
}

public void Dispose()
{
}

public void Init(HttpApplication application)
{
//let's register our event handler
application.PostResolveRequestCache += (new EventHandler(this.Application_OnAfterProcess));
}

private void Application_OnAfterProcess(object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;

//the file being requested is not found
if (!File.Exists(application.Request.PhysicalPath))
{
//replace the "newURL"
//with your own value
string newURL = "product.aspx?ProductID=18";
context.RewritePath(newURL);
}
}
}
}
Now we have to register our HttpModule in the web.config:

<httpModules>
<add type="URLRewrite.ProductPageModule, URLRewrite" name="ProductPageModule" />
<httpModules>

That's it.

Dec 14, 2007

AutoText at GiveAwayOfTheDay.com

Our AutoText tool is featured at GiveAwayOfTheDay today. Today only - get it free of charge (no catch).

Dec 10, 2007

Motivation hint

I deleted unused icons from my desktop and set up a wallpaper like this:



More "motivation wallpapers" can be found at:
http://www.byrdbaggett.com/free/
http://www.anabubula.com/node/15
http://www.simplifiedsuccess.com/wallpapers.asp
http://www.tnpsc.com/ssaver/wallpapers2.htm

Dec 7, 2007

The making of

Just a quick note on what we've been working on for the last two weeks.

After releasing multilingual versions of our forum and helpdesk applications, we received a lot of constructive feedback from our international customers. Mostly, it were feature requests, so the last two weeks were pretty busy.

HelpDesk 2.7.6 (already out) features handy pie-chart diagrams in the "summary" report, customizable email notifications text and many other cool features, including enabled email-notifications in the trial version.

AspNetForum 4.5 (still in development) brings hashed password storage, forum signatures for users, FAQ for users (along with the admin manual) and many other features.

MailJet 2.32 which is also still in development features some minor GUI improvements and a number of performance optimizations.

All these releases are almost finished, and will be out in the next 48 hours.

Dec 6, 2007

Here comes another bubble

Genius Web2.0 music video

Dec 5, 2007

Time management tips

Max Kraynov of Kraynov Investments must have read my mind: he shared a great time-management tip, which I use in my daily work too. Here it is: when I open my notebook and start working on a task, I simply turn on the timer on my watch. That's it.

The timer works like a charm: I don't want to pause it and go fill my coffee mug, or pause it and read an email message. The timer makes me more productive and less distracted. And what's more, I'm not afraid of complex tasks any more, since the timer revealed, that even most complicated tasks take 10-15 minutes to complete.

Interesting links:

  • Google has announced the winner of the Adsense Story Contest today: it is http://www.hometips.com/ - a site that features free articles concerning home improvement, remodeling, repair, redecorating, and do-it-yourself projects. For example, tips on how to make your Christmas tree last for weeks.

    The owner, Don Vandervort, says that the AdSense-revenues went from paying for coffee to paying for lunches to paying for all salaries, overhead, and business development.

  • The owner of cdbaby.com tells 7 reasons why he switched back to PHP after 2 years on Rails. He rewrote his website back to PHP after 2-years struggling with Rails. With the help of a Rails "professional" who quit after all.

    Love his last point: "PROGRAMMING LANGUAGES ARE LIKE GIRLFRIENDS: THE NEW ONE IS BETTER BECAUSE YOU ARE BETTER ... the main reason that any programmer learning any new language thinks the new language is SO much better than the old one is because he’s a better programmer now! You look back at your old ugly PHP code, compared to your new beautiful Ruby code, and think, “God that PHP is ugly!” But don’t forget you wrote that PHP years ago and are unfairly discriminating against it now.."

Dec 1, 2007

PDF contextual advertising

Adobe has announced that it has partnered with Yahoo to offer contextual advertising opportunities in PDF files. Yahoo will automatically insert ad's based on the context of the content PDF file.

Very smart move for Yahoo, IMO.