Feb
16
2012

Theme Google Chrome - The Easy Way!

Ok, so if you've embarked on creating a Google Chrome theme (CRX file) then you know it's a bit time consuming. You need to create the manifest json file, all the images, and figure out what property affects what part of the window.

That's fine if you're a geek and like fiddling with such things, but what if you're not.

Here's the solution:

http://www.themechrome.net

This website makes it really easy. I admit it isn't as versatile as creating a theme from scratch, but it does allow you to handpick a wallpaper background from a large library, and then quickly tweak the color scheme appropriately. Then you click the download/apply button and you're away. Google Chrome themes for non-geeks!

Feb
16
2012

Html.ImageActionLink Custom Helper for MVC

A lot of people override the Ajax helper to create an Ajax.ImageActionLink. This is fine but in some instances it's easier to use an Html.ImageActionLink.

For example, I had a requirement to return a file in a response stream - something that isn't possible with the Ajax method.

The code is fairly simple, and easy to customize to your requirements:

public static MvcHtmlString ImageActionLink(this HtmlHelper helper, string imagePath, 
  string actionName, string controllerName, object routeValues, object imageAttributes, 
  object linkAttributes)
{
var urlHelper = new UrlHelper(helper.ViewContext.RequestContext, 
    helper.RouteCollection);

var aBuilder = new TagBuilder("a");
aBuilder.MergeAttributes(new RouteValueDictionary(linkAttributes));
aBuilder.MergeAttribute("href", urlHelper.Action(actionName, controllerName, 
    routeValues));

var imgBuilder = new TagBuilder("img");
imgBuilder.MergeAttributes(new RouteValueDictionary(imageAttributes));
imgBuilder.MergeAttribute("src", imagePath);

aBuilder.InnerHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

return new MvcHtmlString(aBuilder.ToString(TagRenderMode.Normal));
}
Feb
16
2012

Using conditional statements in an MVC 3 WebGrid column using Razor

Imagine a scenario such as this - "If a person has permission to view an item in the grid then have a hyperlink, otherwise have plain text".

Ok, I tried to conjure up a more interesting scenario but seem to be lacking this morning. There are many situations where you want to render a grid cell based on a condition, and the possibilities are endless.

So how can you do this using the MVC 3 WebGrid Control? The solution, fortunately, is easy peasy. Here's how:

@grid.GetHtml(
columns: grid.Columns(
grid.Column("Conditional Cell Sample", format: @<text>@if(true) { @Html.ActionLink("Go here", "Home") } else { @Html.ActionLink("Or here", "Away") }</text>))
)

Feb
16
2012

ASP.NET C# / MVC - Export an HTML Table to Excel/CSV

Simple stuff. Simply replace output with your table:

Response.ContentType = "application/force-download";
Response.AddHeader("content-disposition", "attachment; filename=output.xls");
Response.Write("<html xmlns:x=\"urn:schemas-microsoft-com:office:excel\">");
Response.Write("<head>");
Response.Write("<META http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
Response.Write("<!--[if gte mso 9]><xml>");
Response.Write("<x:ExcelWorkbook>");
Response.Write("<x:ExcelWorksheets>");
Response.Write("<x:ExcelWorksheet>");
Response.Write("<x:Name>Report Data</x:Name>");
Response.Write("<x:WorksheetOptions>");
Response.Write("<x:Print>");
Response.Write("<x:ValidPrinterInfo/>");
Response.Write("</x:Print>");
Response.Write("</x:WorksheetOptions>");
Response.Write("</x:ExcelWorksheet>");
Response.Write("</x:ExcelWorksheets>");
Response.Write("</x:ExcelWorkbook>");
Response.Write("</xml>");
Response.Write("<![endif]--> ");
Response.Write(output);
Response.Write("</head>");
Response.Flush();

A more advanced method for creation an ExcelResult:ActionResult and extending the MVC Controller can be found here:

http://stephenwalther.com/blog/archive/2008/06/16/asp-net-mvc-tip-2-create-a-custom-action-result-that-returns-microsoft-excel-documents.aspx

Feb
16
2012

jQuery TableSorter Error when table is empty - Error: '0.length' is null or not an object

I had an issue today with the jQuery TableSorter throwing an error when rendering an empty table.

This was my original code:

$("#results-table")     
 .tablesorter({ widthFixed: true, widgets: ['zebra'] })     
 .tablesorterPager({ container: $("#pager"), positionFixed: false });

The error I was getting was:

 
Line: 3 Error: '0.length' is null or not an object

The solution I found was straight forward and requires you to check the number of table rows (tr tags) before calling the TableSorter scripts:

 
if ($("#results-table").find("tr").size() > 1) 
 $("#results-table")
 .tablesorter({ widthFixed: true, widgets: ['zebra'] })
 .tablesorterPager({ container: $("#pager"), positionFixed: false }); 
}
Feb
13
2012

Getting Windows XP "Find In Files" to Search All Files

Windows XP - Find In Unrecognised Files

I needed to run a find in files search on Windows XP but found I wasn't getting any results! It turns out that Windows XP is configured to only search in recognised file types, whereas I was searching in text-based code files with an unknown extension.

Fortunately the solution to this was easy, and this is what I did:

  1. Start -> Run
  2. Enter "mmc %windir%\system32\ciadv.msc" and press "OK".
  3. On the Indexing Service window select Action -> Properties.
  4. In the Generation tab select the option to Index files with unknown extensions.
  5. Press "OK" and close the Indexing Service window.

Now try a search from Start -> Search or by pressing CTRL + F in an Explorer window. In the "A word or phrase in the file:" text box enter the string you want to search for and press "Search". Easy peasy!

 


 

Configuring Search to Find in Unrecognised Files, the Registry Way!

A System Administrator can set the find in files search to look in unrecognised file types by changing the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\ContentIndex

Set the FilterFilesWithUnknownExtensions DWORD value to 1.


 

Configuring the Registry to Recognise Custom File Type Extensions

Ok, so you want to go one step further? This is how you get Windows XP to recognise your previously unrecognised file type:

  • Start -> Run. Enter regedit.
  • In the Registry Editor open the HKEY_CLASSED_ROOT folder. This contains a key for each extension.
  • Search for your extension to see if it exists. If it doesn't then create a new key. It's worth using the .txt key as a reference.
  • Make sure you add a PersistentHandler to the key as this is required for Windows XP to recognise the extenion. You need to change the (Default) value of this key to be the Guid value {5e941d80-bf96-11cd-b579-08002b30bfeb} (same as the PersistentHandler for the .txt entry).
  • Reboot the machine for the registry setting to take effect.
Feb
12
2012

How to Specify Server IP in HttpWebRequest

How to specify server IP in HttpWebRequest

To view the original article please go to http://yoursunny.com/t/2009/HttpWebRequest-IP/

I was writing an HTTP proxy during last weeks. I need to address the origin server with a custom IP address, but I should keep the "Host" header.

I googled about "HttpWebRequest set server IP", "WebRequest modify Host", etc. I read through several posts, and realized:

  • When HttpWebRequest is created, the "Host" header is automatically set to the "host:port" portion of the Uri.
  • Attempt to modify HttpWebRequest.Headers["Host"] will throw an exception.
  • The server IP address of the HTTP Request is determined by the host portion of the Uri, and is automatically resolved against the DNS server.
  • When HttpWebRequest.Proxy is set to use a proxy, the server IP address is determined by resolving the host of Proxy property. I can set the origin server as the proxy, this is called "Proxy hack".
  • When using a proxy, the HTTP Request-Line looks like "GET http://host/ HTTP/1.1" rather than "GET / HTTP/1.1". Every HTTP/1.1 compliant origin server should accept this, but firewalls may think it's a "proxy request" and block it, and some non-compliant servers does not accept it.

Solution

My purpose is to make HttpWebRequest send its request to a custom IP address, but leave the Request-Line as "GET / HTTP/1.1".

After hours of Reflector, I found the solution:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://blogs.msdn.com");//url and Host header
FieldInfo field_ServicePoint_ProxyServicePoint = (typeof(ServicePoint))
.GetField("m_ProxyServicePoint", BindingFlags.NonPublic | BindingFlags.Instance);
req.Proxy = new WebProxy("www.google.com:80");//server IP and port
field_ServicePoint_ProxyServicePoint.SetValue(req.ServicePoint, false);
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

When the above code is executed, I can see the following request in Wireshark:

GET / HTTP/1.1
Host: blogs.msdn.com
Connection: Keep-Alive

And, the request is sent to 64.233.189.99:80, a www.google.com server.

BEHIND THE SCENES

ServicePoint class provides connection management for HTTP connections. A ServicePoint instance is created for each "host:port" combination, and reused across several requests. ServicePoint.m_ProxyServicePoint determines whether this ServicePoint connects to a proxy. When m_ProxyServicePoint is set to false, HttpWebRequest don't think it's a proxy, so the Request-Line becomes "GET / HTTP/1.1".

However, m_ProxyServicePoint is a private property of ServicePoint, so I have to use Reflection to change it.


HttpWebRequest.Host in .Net Framework 4.0

2010-05-31 update: As of .Net Framework 4.0, you can use HttpWebRequest.Host property to set Host header independent from the request URI.

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.google.com");//url path and actual server
req.Host = "blogs.msdn.com");//Host header
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

Jan
15
2012

How to Minimize Outlook to the System Task Tray

If, like me, you have Outlook open all day and get frustrated with too many applications open in the task bar, then the solution is to have it minimise to the system task tray:

  • Right-click the Outlook icon in the Task Tray (bottom-right).
  • Click Hide When Minimized. A tick will appear next to the option.
  • Now when you close Outlook it will remain open and accessible!

Easy peasy!

Mar
19
2011

Google Adwords - Rarely Shown Due To Low Quality Score

I recently created a Google AdWords account and created a simple campaign for www.gazoomy.com. It was going great guns for a number of weeks and bringing in 50 to 100 visitors a day, but all of a sudden it came to a grinding halt.

Each of my keywords was now flagged with the status "Rarely shown due to low quality score". I contacted Google support who replied by saying "Your low Quality Scores are largely due to your landing page quality". I did some research into this but became aware that this wasn't entirely the case, and there are a number of things you can do to prevent or rectify this situation.

The purpose of this article is to share my findings and hopefully help in streamlining AdWord campaigns.

What is the Quality Score?

The Quality Score is a rating that is determined for each keyword you have in your campaign. Google determine this rating by assessing a number of factors such as how relevant your keyword is to your ad text and to a user's search query.

I mentioned earlier that Google modify your Quality Rating based on the relevance of your landing page, which is true, but the CTR of the keyword (KY) is also a major factor in determining the Quality Score rating.

The Quality Score of each individual keyword affects the overall Quality Score of the campaign.

What does it mean by "Rarely shown due to low quality score"?

In short, this means that your ad is no longer running! What could be worse? Why have an Adwords account if you're not driving a single visitor to your site!?

Fortunately, as your ad isn't getting any impressions this also means your Click-through Rate (CTR) is not being affected.

Unfortunately, if your website itself has been given a low Quality Score (such as if they deem the landing page to contain irrelevant content) then this will affect all of your keywords, including any new ones that you create which is not good! Because of this it is worth trying to be pre-emptive by ensuring each keyword in your campaign is productive. I'll discuss this a bit more later.

What is 'Quality Score' and how is it calculated? Google AdWords Support

Landing Page Relevance and Search Engine Optimisation (SEO)

Your landing page must be relevant to your keywords. If you are using keywords such as "hardcore porn" for a site that sells cat-flaps then it won't be long before Google pick up on this inconsistency and lower your Quality Score.

Your keywords, or keyword phrases, need to match up. The keywords need to be relevant and appropriate, and tie in throughout your landing page and the advert itself. Keywords need to be specific in order to receive hits with a high CTR. As a guideline a page should have up to three specific keyword phrases in the Keywords META tag. For example, a page giving away easter eggs could have the keyword phrases "Easter Eggs" and "Free Easter Eggs". Your page itself should utilise these phrases throughout the page, predominently in title tags (<hx>) and the page title as well as in the textual content. Design your GoogleAds advert to utilise these phrases in the title and also the description if possible.

Google will use it's own website ratings to affect your Quality Score. If your website does not meet good SEO guidelines then this will have a knock on affect on your AdWords campaigns. It's not the purpose of this article to discuss SEO, but there is a great deal of information on this subject on this website.

Keyword Click-through Rate (CTR)

It is worth assessing all keyword CTRs within your campaign. If a keyword has a CTR of between 0% and 0.45% then it's performance is poor and will lead to a low QS. If this is the case then there's no point even considering SEO at this stage. If you can't get a CTR of at least 1% then you need to revise your keywords to make them more specific. If the CTR of a keyword is 1.5% or higher then it is performing very well.

With The Lyric VaultI had created a number of generic keywords such as "lyrics", "music", and "words". As you can imagine, there are a plethora of other sites that use such vague keywords. It is worth considering the content of your website and determining more specific keyword combinations. In this case perhaps "Sonic Youth Lyrics" could gain a much higher CTR as anyone typing those words into Google are more than likely to click on your link. It is also worth using square brackets ( [ and ] ) to encompas your phrases. This will require an exact match for the phrase which will make your ad more specific which should lead to a higher CTR. The only caveat is this can limit the amount of clicks you receive, but it is always a far more reliable starting point.

Ad Position

The position of your advert is determined by both the Quality Score and the Maximum Cost Per CLick (CPC). The Click-through Rate (CTR) is the dominating factor in assessing the Quality Score, and Keyword Relevance is the second most important factor. When you create a new campaign you have no CTR, and because of this the Quality Score is based predominantly on Keyword Relevance.

Quick Guidelines on How to Improve the Quality Score

  • Ideally the keyword should be present in the ad headline or ad text.
  • Ensure the keyword has relevance on the landing page. Ideally the keyword should be present in the page title, meta tags, header tags (preferably h1 tags), and appear throughout the content.
  • Having the keyword appear in the landing page URL can help.
  • Make the keywords, or keyword phrases, specific to the page content. The more specific they are the more relevant they are. Use square brackets to encompass keyword phrases.
  • Use your imagination to consider what user's might type into Google to give a good CTR on your keywords.
  • Keep an eye on all keywords in the campaign. Pause or Delete all keywords that have a low CTR, such as below 1%. By removing poor performing keywords you should raise the overall Quality Score of the campaign.
  • Keep your campaigns small and direct. The more generic they are the less successful they will be. Be specific!
  • Include links on your landing page to your privacy policy, contact us, and sitemap pages. AdWords prefers your page to be transparent and easy to navigate.
Feb
4
2011

Bitemporal Database Table Design - The Basics

Bitemporal database design is a method of storing time dependant data records to represent both the history of the facts and the history of changes to the records in the database. Bitemporal databases permit queries over two orthogonal time dimensions: valid time and transaction time. Valid time is the time when a fact is effective in reality. Transaction time denotes the time when the record is effective in the database.

Temporal Tables (Modelling Valid Time)

Most database queries are only concerned with data as it is now, such as "What is the price of an item?". It is tricky to cater for queries such as "What was the price of an item on November 3rd of last year?" or "How long was an item $2.99 for?". By adding two columns for valid start time and valid end time it is possible to represent these queries.

An easy way to implement this is in two phases. Phase one will be to design the database with normal methods, such as normalization. Phase two is to create the temporal additions to necessary tables.

Example 1 - A Temporal Table

 

Here is a conventional table for Product:

ID Name Price
1 Eggs $1.20
2 Milk $0.45
3 Bread $0.30

What he can retrieve from this table is information such as "How much is Milk?".

By adding two date columns then we can perform temporal queries:

ID Name Price From To
1 Eggs $1.20 20/01/2006 13/06/2006
1 Eggs $1.25 13/06/2006 31/12/9999
2 Milk $0.45 20/01/2006 01/01/2007
3 Bread $0.30 20/01/2006 31/12/9999
  • We can see that Eggs were $1.20 until 13th June 2006, and they are currently $1.25.
  • We can see that Milk was $0.45 until 1st Jan 2007. There is currently no price (i.e. Milk is no longer sold).
  • We can see the entire price list at any point in time.

So from this table we can not only deduce the current prices of products, but we can also determine the price history of each product.

Bitemporal Tables (Modelling Valid Time & Transaction Time)

As seen above, the temporal table allows for periods of time to be stored in a database. This is ideal for showing state changes of objects (valid times). Bitemporal design expands on this to model not only valid time, but to additionally model transaction time. Transaction time represents the physical time at which a transaction happened within the database.

Take for example a shipment arriving at a warehouse. This could happen on Wednesday (which would be the valid time that the shipment was in the warehouse). An operator might update the system on the Thursday to state when the shipment arrived. The moment they add the record to the system would be the transaction time. What this allows us to determine at a later date is when that shipment was believed to be in the warehouse, and also when that shipment was known to be in the warehouse according to the database.

Example 2 - A Bitemporal Table

Here is an example of a Stock table that details the stock in various warehouses:

ID Stock Qty WHouseId ValidFrom ValidTo TrxStart TrxEnd OperatorId
101 Milk 12 LOND01 12/11/2006 18/11/2006 13/11/2006 18/11/2006 1111
115 Eggs 15 LOND01 12/11/2006 23/11/2006 13/11/2006 24/11/2006 1111
101 Milk 5 LOND01 18/11/2006 31/12/9999 25/11/2006 31/12/9999 1201
101 Milk 7 LOND02 18/11/2006 31/12/9999 25/11/2006 31/12/9999 1201
115 Eggs 10 LOND01 23/11/2006 31/12/2006 24/11/2006 31/12/9999 1111

From this table we can determine information such as:

  • Warehouse LOND01 had 12 crates of milk in stock between 12th and 18th November. At that point 7 crates were removed and were (likely) delivered to warehouse LOND02.
  • The milk was believed to be moved on 18th November but was only recorded on the 25th.
  • Up to 23rd November there were 15 crates of eggs in LOND01. On this day 5 crates were removed.
  • At the current time, there are 5 crates of milk and 10 crates of Eggs in LOND01, and 7 crates of Milk in LOND02.
  • We can also deduce the average time delay between when an event occurs and when it is logged in the system.
  • The additional OperatorId can tell us who recorded each transaction.

 

Summary

This article has only skimmed the surface of Bitemporal Databases. There are some links below for further research.

For further research I recommend the excellent book Bitemporal Databases: Modeling and Implementation by Canan Eren Atay and Abdullah Uz Tansel:

Page List

    Month List