FAHNZ

MODE

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>

Jul 6 2009

ASP.NET Membership Woes

The problem:

I kept on getting foreign key constraint errors when trying to use ASP.NET (2.0) DeleteUser method:

Membership.DeleteUser(<username>);

All my research on the internet pointed to it being a permissions problem. Like many of the posts I found, this worked fine in my local development database, but in production it would yield this error:

The DELETE statement conflicted with the REFERENCE  constraint
"FK__aspnet_Me__UserI__15502E78". The conflict occurred in  database
"dbname", table "dbo.aspnet_Membership", column 'UserId'.
The  statement has been terminated.

After hours of experimentation with user permissions in the database and research on the problem, the support team at the hosting company I was working with found the solution of setting the references foreign key constraints to cascade upon deletion. I went into SQL Server Management Studio and updated the FKs that were referenced in the errors to cascade upon deletion and voila! Problem solved. Good job CrystalTech support and especially Geoff.

Update: I looked into my local database (that has been working properly) and saw that the foreign keys are not set to cascade deletions, so it still may be some strange permissions issue. Regardless, this seems like an acceptable workaround and it did get those deletions to work (and the usernames freed up).