FAHNZ

MODE

Jan 7 2011

Transact SQL LastIndexOf Function

I can’t help but think there may be a more efficient way to do this, but I’m posting here anyway. I welcome updates to make this better…

CREATE FUNCTION LastIndexOf
(
@substring nvarchar(max),
@stringToSearch nvarchar(max)
)
RETURNS int
AS
BEGIN

RETURN
LEN(@stringToSearch)
- LEN(@substring)
+ 2
- CHARINDEX(REVERSE(@substring), REVERSE(@stringToSearch))

END
GO

I still can’t believe I didn’t find much on this (beyond a single character search) on Google. Go figure.


Aug 15 2010

JavaScript Binary Search Function

Coffee beansI was looking into binary search functions lately and decided to comment this JavaScript binary search function I found (original is at http://www.dweebd.com/javascript/binary-search-an-array-in-javascript/) to help ensure that I had a good grasp on everything that was going on in it. Thought it might be useful for others, so I expanded my comments (read: commented the holy hell out of it) for posting here. Enjoy!

<script type="text/javascript">
 // Custom sort comparator
 function sortNumericAscending(a, b) {
 return a - b;
 }

 // Based off of http://www.dweebd.com/javascript/binary-search-an-array-in-javascript/

 // Extend the array object to include a new function to perform a binary search.
 // Since a binary search requires the array to be sorted, we can optionally
 // pass in the name of the function to do the comparison as well as the value to find.
 Array.prototype.binarySearch = function binarySearch(valueToFind, comparator) {
 var
 // The lower bound of the array, initally set to the true lower bound.
 lowerBound = 0,

 // The upper bound of the array, initally set to the true upper bound.
 upperBound = this.length - 1,

 // Stores the median index of the array.
 medianIndex,

 // Stores the result after we compare the value to find
 // with the value at the current median index of the array.
 comparisonResult;

 // As the loop progresses, the lower and upper bounds
 // will halve upon each iteration and eventually meet.
 while (lowerBound <= upperBound) {

 // Determine and store the median index.
 medianIndex = parseInt((lowerBound + upperBound) / 2, 10);

 // Check to see if a comparator was passed in.
 if (comparator == null) {

 // If there was no comparator to use, then use the default comparator.
 if (this[medianIndex] == valueToFind) {
 // If the comparison shows that the value that's at the current median index of the array
 // is equal to the value to find then set the comparison result to zero.
 comparisonResult = 0;
 }
 else {
 // If the comparison shows that the value that's at the current median index of the array
 // is less than the value to find then set the comparison result to one. If the comparison
 // shows that the median array value is greater than the value to find, then set the
 // comparison result to negative one.
 comparisonResult = (this[medianIndex] < valueToFind) ? 1 : -1;
 }
 }
 else {
 // If a comparator was supplied, then use it to determine
 // if the value is greater, lesser, or equal to the value to find.
 // It is presumed that this comparator is the same that was used to sort the array
 comparisonResult = comparator(this[medianIndex], valueToFind);
 }

 // If the comparison shows that the value that's at the current median index of the array
 // is less than the value to find then we know we'll need to look at the top half of this array.
 if (comparisonResult < 0) {

 // Set the new lower bound to just above the current median index
 // so that the next pass will only look at the top half of this array.
 lowerBound = medianIndex + 1;

 // Since the comparison result did not show that the values were equal
 // and we've set up the new bounds of the array to search on next,
 // then just disregard the rest of this iteration of the loop and contine with the next iteration.
 continue;
 }

 // If the comparison shows that the value at the current median index of the array
 // is greater than the value to find then we know we'll need to look at the bottom half of this array.
 if (comparisonResult > 0) {

 // Set the new lower bound to just below the current median index
 // so that the next pass will only look at the bottom half of this array.
 upperBound = medianIndex - 1;

 // Since the comparison result did not show that the values were equal
 // and we've set up the new bounds of the array to search on next,
 // then just disregard the rest of this iteration of the loop and contine with the next iteration.
 continue;
 }

 // We can only get to this point if the comparison result was equal
 // so we can return the value found at the last median index of the array.
 return this[medianIndex];
 }

 // If we searched the entire array and didn't locate
 // the value to find then just return null.
 return null;
 };

 // Testing the implementation.
 var newArray = [0, 3, 10, 4, 1, 2];

 // Default sort comparator.
 newArray.sort(); // default sort is alphanumeric
 document.write("newArray.binarySearch(3)=" + newArray.binarySearch(3));

 // Custom sort comparator.
 newArray.sort(sortNumericAscending);
 document.write("newArray.binarySearch(3, sortNumericAscending)=" + newArray.binarySearch(3, sortNumericAscending));
 </script>

I still think there’s a good chance I missed something so if you find anything amiss, please let me know so I can fix.


Nov 17 2009

Bubbling UserControl Events

This scenario has bitten me before. User control events fire after page events. This can be a problem if an update within the user control needs to be reflected in the outer page container. The solution is to “bubble” the event from the user control into the page so it can react accordingly. So, as much for my reference as anyone else’s, here’s some quick ‘n dirty code to bubble events from an ASP.NET user control to the page that contains it:

User Control Code:

public partial class SamplePage : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    // "SampleUserControl1" is the ID of the control that has already been placed in the HTML of the page
    SampleUserControl1.BubbleEventHappened += new EventHandler(BubbleEventHappened);
  }

  private void BubbleEventHappened(object sender, EventArgs e)
  {
    // code to react to bubbled event goes here
  }
}

Page (that contains the User Control) Code:

public partial class SamplePage : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    // "SampleUserControl1" is the ID of the control that has already been placed in the HTML of the page
    SampleUserControl1.BubbleEventHappened += new EventHandler(BubbleEventHappened);
  }

  private void BubbleEventHappened(object sender, EventArgs e)
  {
    // code to react to bubbled event goes here
  }
}

There. That wasn’t so bad!


Oct 26 2009

My Test ASP.NET Email Page

I need to test out this kind of functionality all the time. I’ve found it helpful to post this file to the web server that I need to be able to send email from and then tell the person who has control over the configuration of the email server to use this page to test with.

What follows is a self-contained ASP.NET page that allows the user to input all the information needed to configure how the email parameters are handled in the code in order to send a test message from the web server. This was recently (and quickly) converted from an ancient version in VB.NET and could use some serious tweaking; I’ll update the code here if I get around to it.  ;-)

<%@ Page Language="c#" Strict="false" %>
<%@ Import Namespace="System.Net.Mail" %>
<script language="c#" runat="server">
private string _mailServer;
private int _mailServerPort = 0;
private string _username;
private string _password;

private string _toAddress;
private string _fromAddress;
private string _subject;
private string _body;

private void btnSubmit_Click(Object sender, EventArgs e)
{
if (Page.IsValid)
{
_mailServer = txtMailServer.Text;
_username = txtUsername.Text;
_password = txtPassword.Text;

if (!string.IsNullOrEmpty(txtMailServerPort.Text)) { _mailServerPort = int.Parse(txtMailServerPort.Text); }

_toAddress = txtMailTo.Text;
_fromAddress = txtMailFrom.Text;
_subject = txtSubject.Text;
_body = txtBody.Text;

MailMessage message = new MailMessage(_fromAddress, _toAddress);

message.Headers.Add("Reply-To", _fromAddress);
message.Subject = _subject;
message.Body = GetResponse(_body);

SmtpClient mailer = new SmtpClient(_mailServer);
if (_mailServerPort > 0) { mailer.Port = _mailServerPort; }
if (!string.IsNullOrEmpty(_username)) { mailer.Credentials = new System.Net.NetworkCredential(_username, _password); }
mailer.EnableSsl = chkEnableSsl.Checked;

try
{
mailer.Send(message);
lblResponse.Text = CleanHtml(GetResponse("Email message appeared to send successfully."));
}

catch (Exception ex)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("There was an error sending the email message:");
sb.Append("\r\n");
sb.Append("\r\n");

sb.Append(ex.Message);
sb.Append("\r\n");
sb.Append("\r\n");

sb.Append(ex.StackTrace);

lblResponse.Text = CleanHtml(GetResponse(sb.ToString()));
}
}
}

private string GetResponse(string msg)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(msg);
sb.Append("\r\n");
sb.Append("\r\n");

sb.Append("Mail Server: ");
sb.Append(_mailServer);
if (_mailServerPort > 0) { sb.Append(":" + _mailServerPort.ToString()); }
sb.Append("\r\n");

if (!string.IsNullOrEmpty(_username))
{
sb.Append("Logon Username: ");
sb.Append(_username);
sb.Append("\r\n");
}

sb.Append("Enable SSL: ");
sb.Append(chkEnableSsl.Checked.ToString());
sb.Append("\r\n");
sb.Append("\r\n");

sb.Append("To Address: ");
sb.Append(_toAddress);
sb.Append("\r\n");

sb.Append("From Address: ");
sb.Append(_fromAddress);
sb.Append("\r\n");

sb.Append("Subject: ");
sb.Append(_subject);
sb.Append("\r\n");

sb.Append("Body: ");
sb.Append(_body);
sb.Append("\r\n");

return sb.ToString();
}

public enum ConvertHtml
{
GtLt = 1,
SpecialSingleCharacters = 2,
CrLfToBr = 4,
BrToCrLf = 8,

ForHtmlEmail = 6,
ForWeb = 7
}

public static string CleanHtml(string original)
{
return CleanHtml(original, ConvertHtml.ForWeb);
}

public static string CleanHtml(string original, ConvertHtml convertFormat)
{
System.Text.StringBuilder cleaned = new System.Text.StringBuilder();
cleaned.Append(original);

if ((convertFormat & ConvertHtml.GtLt) == ConvertHtml.GtLt)
{
cleaned = cleaned.Replace("<", "&lt;");
cleaned = cleaned.Replace(">", "&gt;");
}

if ((convertFormat & ConvertHtml.SpecialSingleCharacters) == ConvertHtml.SpecialSingleCharacters)
{
cleaned = cleaned.Replace(" & ", " &amp; ");
cleaned = cleaned.Replace("\"", "&quot;");
}

if ((convertFormat & ConvertHtml.BrToCrLf) == ConvertHtml.BrToCrLf)
{
cleaned = cleaned.Replace("<br>", "\r\n");
}

if ((convertFormat & ConvertHtml.CrLfToBr) == ConvertHtml.CrLfToBr)
{
cleaned = cleaned.Replace("\r\n", "<br>");
cleaned = cleaned.Replace("\r", "<br>");
cleaned = cleaned.Replace("\n", "<br>");
}

return cleaned.ToString();
}
</script>
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server" id="Head1">
<title>Test ASP.NET Email</title>
<style type="text/css">
body { font: 76% verdana; }
.tbl { border-collapse: collapse; }
.tbl td { border: solid 1px #ccc; padding: 5px; }
.tb { width: 300px; }
</style>
</head>

<body>
<form id="form1" runat="server">
<div>
<h1>Test ASP.NET Email</h1>
<p><asp:label id="lblResponse" runat="server" forecolor="Red"></asp:label></p>
<table>
<tr>
<td>Mail Server*</td>
<td><asp:textbox id="txtMailServer" runat="server" CssClass="tb"></asp:textbox><asp:requiredfieldvalidator id="rfvMailServer" runat="server" errormessage="required" controltovalidate="txtMailServer" Display="Dynamic"></asp:requiredfieldvalidator></td>
</tr>
<tr>
<td>Mail Server Port</td>
<td><asp:textbox id="txtMailServerPort" runat="server" CssClass="tb"></asp:textbox></td>
</tr>
<tr>
<td>Logon Username</td>
<td><asp:TextBox runat="server" ID="txtUsername" CssClass="tb"></asp:TextBox></td>
</tr>
<tr>
<td>Logon Password</td>
<td><asp:TextBox runat="server" ID="txtPassword" TextMode="Password" CssClass="tb"></asp:TextBox></td>
</tr>
<tr>
<td></td>
<td><asp:CheckBox runat="server" ID="chkEnableSsl" Text="Enable SSL" /></td>
</tr>
<tr>
<td colspan="2">&nbsp;</td>
</tr>

<tr>
<td>Mail To*</td>
<td><asp:textbox id="txtMailTo" runat="server" CssClass="tb"></asp:textbox><asp:requiredfieldvalidator id="rfvMailTo" runat="server" errormessage="required" controltovalidate="txtMailTo" Display="Dynamic"></asp:requiredfieldvalidator></td></tr>
<tr>
<td>Mail From*</td>
<td><asp:textbox id="txtMailFrom" runat="server" CssClass="tb"></asp:textbox><asp:requiredfieldvalidator id="rfvMailFrom" runat="server" errormessage="required" controltovalidate="txtMailFrom" Display="Dynamic"></asp:requiredfieldvalidator></td></tr>
<tr>
<td>Subject*</td>
<td><asp:textbox id="txtSubject" runat="server" CssClass="tb">Test Message</asp:textbox><asp:requiredfieldvalidator id="rfvSubject" runat="server" errormessage="required" controltovalidate="txtSubject" Display="Dynamic"></asp:requiredfieldvalidator></td></tr>
<tr>
<td>Body*</td>
<td><asp:textbox id="txtBody" runat="server" textmode="MultiLine" rows="6" CssClass="tb">This is a test message.</asp:textbox><asp:requiredfieldvalidator id="rfvBody" runat="server" errormessage="required" controltovalidate="txtBody" Display="Dynamic"></asp:requiredfieldvalidator></td></tr>
<tr>
<td colspan="2">&nbsp;</td></tr>
<tr>
<td></td>
<td><asp:button id="btnSubmit" runat="server" text="Send" onclick="btnSubmit_Click"></asp:button></td></tr>
</table>
</div>
</form>
</body>
</html>