Friday, October 17, 2008

Regex match html content without screwing up the tags

When needing to highlight words in a string containing HTML we found we soon ran into problems when the word we were searching for appeared in the middle of a tag..

Imagine the example: 


If I wanted to bold all occurances of geekzilla, I'd usually do this:

unfortunately, when dealing with HTML rather than just text, this will screw my tag and produce the following



We did a lot of googling and found loads of people discussing ways to ignore the tags. Suggetions rainged from sax parsers to character by character loops (nasty).

Armed with an excellent regex for matching an entire HTML tag we came up with the following solution
Our Solution

Use a custom Regex match evaluator to ignore any tags. This works well and is very fast. There may be a slicker way to do this, I hope someone is inspired enough to figure it out and post a comment


private string replaceString = "";
public string Parse(string content)
{
const string regTagName = @"<.[^>]*>";

Regex reg = new Regex(@"(" + regTagName + ")|(geekzilla)",
RegexOptions.IgnoreCase | RegexOptions.Multiline);

// this is what I'd like to replace the match with
replaceString = "$1";

// do the replace
content = reg.Replace(content, new MatchEvaluator(MatchEval));

return content;
}

protected string MatchEval(Match match)
{
if (match.Groups[1].Success)
{
// the tag
return match.ToString();
}
if (match.Groups[2].Success)
{
// the text we're interested in
return Regex.Replace(match.ToString(), "(.+)", replaceString);
}
// everything else
return match.ToString();
}

Highlighting keywords in text using Regex.Replace

Why

I needed to take some text and bold certain keywords before returning the data to the web browser to enhance my Search Engine Optimization

Example

The following example shows how I achieved this although it does contain dummy data. I created a new C# 2005 Console App and added the following to the Main method:

string keywords = "Cat, rabbit, dog,hound, fox";
string text = "The cat spoke to the dog and told him what the rabbit did to the fox while the hound was sleeping.";

Console.WriteLine(HighlightKeywords(keywords, text));
Console.ReadLine();


Then added the follwoing static methods:

private static string HighlightKeywords(string keywords, string text)
{
// Swap out the , for pipes and add the braces
Regex r = new Regex(@", ?");
keywords = "(" + r.Replace(keywords, @"|") + ")";

// Get ready to replace the keywords
r = new Regex(keywords, RegexOptions.Singleline | RegexOptions.IgnoreCase);

// Do the replace
return r.Replace(text, new MatchEvaluator(MatchEval));
}

private static string MatchEval(Match match)
{
if (match.Groups[1].Success)
{
return "" + match.ToString() + "";

}

return ""; //no match
}

Cleaning a string using a regular expression ready for placing in a URL


public static string CleanForUrl(string text)
{
return Regex.Replace(text, @"[^a-z^A-Z^0-9^-]", "-");
}

Thursday, October 16, 2008

Enabling HttpGet and HttpPost for web services

If your web application needs to accept incoming webservice method requests based on the GET and POST protocols then add the following lines to your web.config file.


Select a row in an asp:GridView without using a Select Command

ASP.Net's GridViews can be quite useful, but beware of binding them to huge datasets as this has an overhead on the ViewState.
Often you'll want to display a number of columns on each line and row space becomes an issue. What's worse is you then have to create a SELECT command button to be able to access that line's data.



Use the following code on the event OnRowDataBound to eliminate the need for the SELECT command field and save yourself some valuable space.
Here is the HTML to create a GridView, I'm displaying a list of people, and the key for each record is the PERSON_ID.


The key event to note is the OnRowDataBound, use the following code to create SELECT functionality on the row.


protected void PeopleGridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            e.Row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';";
            e.Row.Attributes["onmouseout"] = "this.style.textDecoration='none';";

            e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this.PeopleGridView, "Select$" + e.Row.RowIndex);
        }
    }

Each row will then behave like a link, and when you select one it can drive the behavior of another control(s) on your page, possibly a DetailsView allowing you to INSERT a complete record to the database.

Perform actions before a row is deleted from a GridView or a DetailsView

I'm a big fan of caching objects on the web server, really saves loads of unneccessary trips to SQL Server and those precious resources.
In a recent project I built some administration screens to change the configuration of my site, as it happens this data was cached on the server for 8 hours at a time.
Rather than let the cache expire for the changes to be picked up I leveraged a feature of the GridView and DetailsView controls I was using, to clear the cache on a DELETE or INSERT by simply using the RowDeleting Event on the GridView and the ItemInserting on the DetailsView.
Here's the code:

protected void ProductCategoriesGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
string categoryID =((HiddenField)ProductCategoriesGridView.Rows[e.RowIndex].FindControl("CATEGORY_ID")).Value;
try
{
Cache.Remove("PRODUCTS_" + categoryID);
}
catch (Exception)
{
}
}



Using the RowIndex property of the GridViewDeleteEventArgs, you can then access the row that you're just about to delete. Here I have a hidden field that holds a key suffix to a cached object. This isn't a key in my GridView or I would have used the DataKeys property.
When I need to insert some data via the DetailsView I used the following code on the ItemInserting event.


protected void ProductCategoryDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    string categoryID = ((DropDownList)ProductCategoryDetailsView.Rows[0].FindControl("CategoryDropDownList")).SelectedValue;
  try
    {
         Cache.Remove("PRODUCTS_" + categoryID);
    }
    catch (Exception)
    {
    }
}


Here I'm grabbing the key suffix from a dropdown list in the DetailsView. I clear the cache and perform the INSERT to the database. This will ensure that the latest data is loaded and cached for the next request.

Rendering a Control to a String

This is a really handy little function for rendering a control to a string. Really handy if you want to pass back rendered HTML from a StaticPageMethod or WebService.

private static string GetRenderedControl(Control control)
{
HtmlTextWriter writer = new HtmlTextWriter(new StringWriter());
control.RenderControl(writer);
return writer.InnerWriter.ToString();
}

Monday, October 13, 2008

Call ServerSide function from Javascript

aspx file:
aspx.cs file:
private void Page_Load(object sender, System.EventArgs e)
{
 if ( this.IsPostBack )
 {
  string eventArgument = (this.Request["__EVENTARGUMENT"] == null) ? string.Empty : this.Request["__EVENTARGUMENT"];
  if ( eventArgument == "CallServerSideFunction1" )
   ServerSideFunction1();
 
 }
}
private void ServerSideFunction1()
{
 this.Response.Write("ServerSideFunction1 called");
}

Thursday, October 9, 2008

Generating Sequence Number in DataGrid with Paging

In my previous article(  Generating Sequence Number in DataGrid) , i have explained how to generate sequence number (row number) in a DataGrid. This method can be easily implemented in DataGrid if there is no paging involved in that DataGrid. But same wont work in DataGrid, if paging is also there in DataGrid. To know how to do paging in DataGrid, refer this article Paging in DataGrid
If you implement this method, in the all the pages Sequence number will start from one only. But our requirement is not that, sequence number has to continue in all the pages.
For example if i am going to second page with Pagesize 10, then sequence number  should start from 11. To achieve this result we need to slightly tweak our previous method. Code snippet for implementing this method is,  

     
                  
                                     
                        <%# (DataGrid1.PageSize*DataGrid1.CurrentPageIndex)+ Container.ItemIndex+1%>
                
                 
           
           
                                
           
                 
                       
            
        
   


Tweak in the code is very simple, instead of only using container.itemindex to get the sequence number. You need to use Pagesize and currentpageindex to find out the starting number of that page and then add container.itemindex to that.

Avoid Using Count(*)

If you need to return the total table's row count, you can use
alternative way instead of SELECT COUNT(*) statement.
Because SELECT COUNT(*) statement make a full table scan to return the
total table's row count, it can take very many time for the large
table. There is another way to determine the total row count in a
table. You can use sysindexes system table, in this case. There is
ROWS column in the sysindexes table. This column contains the total
row count for each table in your database. So, you can use the
following select statement instead of SELECT COUNT(*):

SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2

you can improve the speed of such queries in several times.

Wednesday, October 8, 2008

Password Hashing in C#

In normal circumstances when you store passwords in a database in clear text, you simply authenticate a user by finding the password associated with the username supplied and comparing the inputted password with the database value. Authentication with hashed passwords is obviously a little different than the traditional approach. You will create a hash value of the user inputted password and compare it with the already hashed value in your database. If the two hashed strings are equal, go ahead and authenticate the user. For example:
string strUserInputtedHashedPassword = 
             FormsAuthentication.HashPasswordForStoringInConfigFile(
                                      tbPassword.Text, "sha1");
if(strUserInputtedHashedPassword == GetUsersHashedPasswordUsingUserName(tbUserName.Text))
{
   // sign-in successfull
}
else
{
   // sign-in failed
}
 
protected TextBox tbPassword;
  protected Literal liHashedPassword;

  
  private void Page_Load(object sender, System.EventArgs e)
  {
   // Put user code to initialize the page here
  }
  public void btnHash_Click(object sender, EventArgs e)
  {
   if(tbPassword.Text.Length > 0)
   {
    string strHashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(tbPassword.Text, "sha1");
    liHashedPassword.Text = "Hashed Password is: " + strHashedPassword;    
   }
  }

Convert hex color to .net Color object

Convert hex color to .net Color object
The syntax for using the ColorTranslator to convert a hex value:
Color black = ColorTranslator.FromHtml("#000000");
Because it took me more than a minute to find, I decided to post it for future reference…

Monday, October 6, 2008

Embed text in Image using ASP.NET

Sometimes, it is nice to have a text caption embedded into an image, rather than display the caption in HTML. Fortunately, this is fairly straightforward in ASP.NET.

image_text.aspx

<%@ Page Language="c#"%>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Drawing2D" %>

private void Page_Load(object sender, System.EventArgs e)
{
  Bitmap bmp= new Bitmap(Server.MapPath(Request.QueryString["i"]));
  Graphics g=Graphics.FromImage(bmp);
  g.SmoothingMode = SmoothingMode.AntiAlias ;
  g.DrawString(Request.QueryString["t"],
  new Font("verdana",12),SystemBrushes.WindowText, 1, 1);
  Response.ContentType="image/jpeg";
  bmp.Save(Response.OutputStream, bmp.RawFormat) ;
}

Get Host by IP adress

Get Host by IP adress

 string IPAdress = "127.0.0.1";
IPHostEntry IPHostEntryObject = Dns.GetHostEntry(IPAdress);
Console.WriteLine(IPHostEntryObject.HostName)

Make C# Application Wait Amount of Time

Stalling for Time

C#.Net programs sometimes need to wait a certain amount of time before carrying out the rest of the code. For example, an application that reminds users every 15 minutes to do something has to stall for 15 minutes.
While you can do time-measuring algorithms in C# with the Timer class, let's try to use a simpler way...

DateTime vs StopWatch

If you remember the code speed test utility, there are two C# classes (not including Timer) that can measure time, the DateTime class and the System.Diagnostics.StopWatch class.
The DateTime class is good if you want to work with loose amounts of time, meaning that 14.98 seconds would be okay if you were aiming for 15.
The StopWatch class on the other hand is as precise as you can get with only C# code.
Whichever one you use is up to you...

How to Stall for Time

The basic way to stall for time in C# will be to use a while loop. In theory, we just need the loop to run in circles until enough time has passed. The example uses DateTime, but the StopWatch object would work too...
DateTime start = DateTime.Now;

while (DateTime.Now.Subtract(start).Seconds < 15)
{
}
That source code will work, but it is not elegant just yet. The problem is it freezes the C# program until the 15 seconds are over. Even worse, it eats up the CPU attention.
To keep the application responsive, you need to add the following C# line inside the loop:
Application.DoEvents();
That makes the applicaiton process its messages even while the loop is running. Thus normal UI interaction is kept running.
To prevent the CPU from going insane:
System.Threading.Thread.Sleep(1);
Technically that C# code can reduce how accurate the stalling time is, but giving the loop a 1 millisecond break per iteration, frees up the CPU.
Remember, both of those lines go inside the loop. And with that, you now have an elegant way to stall for time with simple C# code.

Sunday, October 5, 2008

Optimizing C# Application

Optimizing C# Application

7 Ways To Optimize C# Code

Code optimization is an important aspect of writing an efficient C# application. The following tips will help you increase the speed and efficiency of your C# code and applications.

1. Knowing when to use StringBuilder

You must have heard before that a StringBuilder object is much faster at appending strings together than normal string types.
The thing is StringBuilder is faster mostly with big strings. This means if you have a loop that will add to a single string for many iterations then a StringBuilder class is definitely much faster than a string type.
However if you just want to append something to a string a single time then a StringBuilder class is overkill. A simple string type variable in this case improves on resources use and readability of the C# source code.
Simply choosing correctly between StringBuilder objects and string types you can optimize your code.

2. Comparing Non-Case-Sensitive Strings

In an application sometimes it is necessary to compare two string variables, ignoring the cases. The tempting and traditionally approach is to convert both strings to all lower case or all upper case and then compare them, like such:
str1.ToLower() == str2.ToLower()
However repetitively calling the function ToLower() is a bottleneck in performace. By instead using the built-in string.Compare() function you can increase the speed of your applications.
To check if two strings are equal ignoring case would look like this:
string.Compare(str1, str2, true) == 0 //Ignoring cases
 
The C# string.Compare function returns an integer that is equal to 0 when the two strings are equal.

3. Use string.Empty

This is not so much a performance improvement as it is a readability improvement, but it still counts as code optimization. Try to replace lines like:
if (str == "")
with:
if (str == string.Empty)
 
This is simply better programming practice and has no negative impact on performance.
Note, there is a popular practice that checking a string's length to be 0 is faster than comparing it to an empty string. While that might have been true once it is no longer a significant performance improvement. Instead stick with string.Empty.

4. Replace ArrayList with List<>

ArrayList are useful when storing multiple types of objects within the same list. However if you are keeping the same type of variables in one ArrayList, you can gain a performance boost by using List<> objects instead.
Take the following ArrayList:
ArrayList intList = new ArrayList();
intList.add(10);
return (int)intList[0] + 20;
 
Notice it only contains intergers. Using the List<> class is a lot better. To convert it to a typed List, only the variable types need to be changed:
List<int> intList = new List<int>();

intList.add(10)

return intList[0] + 20;
There is no need to cast types with List<>. The performance increase can be especially significant with primitive data types like integers.

5. Use && and || operators

When building if statements, simply make sure to use the double-and notation (&&) and/or the double-or notation (||), (in Visual Basic they are AndAlso and OrElse).
If statements that use & and | must check every part of the statement and then apply the "and" or "or". On the other hand, && and || go thourgh the statements one at a time and stop as soon as the condition has either been met or not met.
Executing less code is always a performace benefit but it also can avoid run-time errors, consider the following C# code:
if (object1 != null && object1.runMethod())
 
If object1 is null, with the && operator, object1.runMethod()will not execute. If the && operator is replaced with &, object1.runMethod() will run even if object1 is already known to be null, causing an exception.

6. Smart Try-Catch

Try-Catch statements are meant to catch exceptions that are beyond the programmers control, such as connecting to the web or a device for example. Using a try statement to keep code "simple" instead of using if statements to avoid error-prone calls makes code incredibly slower. Restructure your source code to require less try statements.

7. Replace Divisions

C# is relatively slow when it comes to division operations. One alternative is to replace divisions with a multiplication-shift operation to further optimize C#. The article explains in detail how to make the conversion.

 

C# Unique Hardware ID

C# Unique Hardware ID

Obtaining the Computer's Unique ID

Each computer has certain hardware pieces that carry serial numbers. Using these serial numbers it is possible to obtain a hardware ID in C# that is unique to a certain computer only.
Keep in mind there are some serial numbers that are not true hardware serials, as in they change when the harddrive is formatted.
We are going to use the first CPU's ID and the first Harddrive's actual serial, neither of which change upon formatting. Using C# code, you can combine those serials into a unique hardware ID

Hardware IDs

Both ID's will require the System.Management.dll reference. If you create a New Project the reference will not be added automatically.
Add it manually by right-clicking on "References" (in the Solution Explorer) and hit "Add Reference...". Scroll down to System.Management (in the .Net tab) and add it...

CPU ID

Note that finding the CPU unique hardware ID is a bit different than normal C# programming. We'll be accessing the property through string expressions rather than strong-typed properties.
string cpuInfo = string.Empty;
ManagementClass mc = new ManagementClass("win32_processor");
ManagementObjectCollection moc = mc.GetInstances();

foreach (ManagementObject mo in moc)
{
     if (cpuInfo == "")
     {
          //Get only the first CPU's ID
          cpuInfo = mo.Properties["processorID"].Value.ToString();
          break;
     }
}
return cpuInfo;
The function runs with a bit of a delay, but nothing too terrible.

Hard Drive ID (Volume Serial)

Finding a unique volume serial works very similarly and luckily a bit simplier:
ManagementObject dsk = new ManagementObject(@"win32_logicaldisk.deviceid=""" + drive + @":""");
dsk.Get();
string volumeSerial = dsk["VolumeSerialNumber"].ToString();

Deriving a Unique ID

The two serials can be combined in any way you wish. Use simple C# string functions or complex one. For example, after testing it across several systems, I decided to truncated serveral 0's from the Volume Serial.
A quick note. What is the point of a unique hardware ID? The most common use for such information is for licensing software that is tailored to a specific computer of set of computers. With a bit of C# encryption functions, it can be an effective method.
Download the C# project files to see for yourself the speed of the combined functions and the complexity of the serial number...