Archive

Archive for the ‘ASP.NET’ Category

Simple pluggable forum software

January 26, 2006 Leave a comment

We had a requirement to provide a support forum
inour
online store for Secret
Server
which led to the
classic”Buy vs. Build” decision.

Build: The
requirementswere very simpleand it could be developed in-house but
who wants to write simple forum code when it has been done many times
before?!

Buy:Most of available
optionswere too sophisticated for our requirementswhich could make
integration difficult (either no source code provided or overly complicated
software or restrictive licensing).

Then I found the Riverside
Internet Forums
on CodeProject by
Mike
Puddephat
. The forum uses 4 generic database tables and has custom
controls in one dll (with source code provided). You can add the custom
control with a unique “forum id” to any ASPX page and it just works! It
was easy to integrate and achieve “single sign on” with our existing system by
ensuring that our user maintenance code keeps the WS_Users (a forum table) up to
date.

Voila! Secret Server now has an online support
forum
!

Jonathan Cogley isthe CEO and founder of
thycotic, a .NET consulting company and ISV in Washington DC. thycotic has
just released
Thycotic Secret Server which is a secure web-based solution to both “Where is my Hotmail
password?” and “Who has the password for our domain name?”. Secret Server
isthe leader in secret management and sharing within
companies and teams.

Secret Server now supports ASP.NET 2.0!

January 11, 2006 Leave a comment

Our product, Secret Server, now supports ASP.NET
2.0.Testing on ASP.NET 2.0started with a horrible crash on the
secret view page resulting in the typical “but it worked fine in
1.1?!”.

Here is the exception stack trace, we were
seeing:

Message: Collection was modified; enumeration
operation may not execute.
Exception:
System.InvalidOperationException
StackTrace:
at
System.Web.UI.ControlCollection.ControlCollectionEnumerator.MoveNext()
at
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection
children)
at
System.Web.UI.Control.RenderChildren(HtmlTextWriter
writer)
at
System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter
writer)
at
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter
writer)
at
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,
ControlAdapter adapter)
at
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter
adapter)
at
System.Web.UI.Control.RenderControl(HtmlTextWriter
writer)
at
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection
children)
at
System.Web.UI.Control.RenderChildren(HtmlTextWriter
writer)
at
System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter
writer)
at
System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter
output)
at
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,
ControlAdapter adapter)
at
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter
adapter)
at
System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter
writer)
at
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection
children)
at
System.Web.UI.Control.RenderChildren(HtmlTextWriter
writer)
at
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter
writer)
at
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,
ControlAdapter adapter)
at
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter
adapter)
at
System.Web.UI.Control.RenderControl(HtmlTextWriter
writer)
at
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection
children)
at
System.Web.UI.Control.RenderChildren(HtmlTextWriter
writer)
at System.Web.UI.Page.Render(HtmlTextWriter
writer)
at
Thycotic.Foundation.WebControls.BasePage.RenderMiddle(HtmlTextWriter
writer)
at
Thycotic.Foundation.WebControls.BasePage.RenderAll(HtmlTextWriter
writer)
at
Thycotic.Foundation.WebControls.BasePage.Render(HtmlTextWriter
writer)
at
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,
ControlAdapter adapter)
at
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter
adapter)
at
System.Web.UI.Control.RenderControl(HtmlTextWriter
writer
at System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Putting on our deerstalker and tapping our pipe,
this stack trace still doesn’t reveal the culprit and is notparticularly
helpful at all. The exception message sounds like the erroryou get
when modifying the collection insidea foreach loop, right? But
where?! -it appears to behappening in the Render method of one of
the controls on the page – but which one?! The error was finally trapped
down through a slow process of trial and error to a custom webcontrol (in a
compiled referenced dll, no less!)that has a curious ReadOnly capability
that works fine in 1.1 but dies miserably in 2.0.

Here is the code:

  1 protected override void Render(HtmlTextWriter writer)
  2 {
  3 	if (_readOnly)
  4 	{
  5 		Label label = new Label();
  6 		label.ID = this.ID;
  7 		label.Text = this.Text;
  8 		ReplaceSelfWithControl(label);
  9 		label.RenderControl(writer);
 10 	}
 11 	else
 12 	{
 13 		base.Render(writer);
 14 	}
 15 }
 16
 17 private void ReplaceSelfWithControl(Control control)
 18 {
 19 	this.Parent.Controls.AddAt(this.Parent.Controls.IndexOf(this), control);
 20 	this.Parent.Controls.Remove(this);
 21 }

The problem (as you probably have guessed) is the
ReplaceSelfWithControl method where the TextBox reaches back into the Controls
collection and replaces itself with a Label. Changing the code to simply render
the HTML output fixed the problem, like so:

  1 protected override void Render(HtmlTextWriter writer)
  2 {
  3 	if (_readOnly)
  4 	{
  5 		if (this.CssClass != null && this.CssClass.Trim() != "")
  6 		{
  7 			writer.AddAttribute("class", this.CssClass);
  8 		}
  9 		writer.AddAttribute("id", this.ClientID);
 10 		writer.RenderBeginTag(HtmlTextWriterTag.Span);
 11 		writer.Write(this.Text);
 12 		writer.RenderEndTag();
 13 	}
 14 	else
 15 	{
 16 		base.Render(writer);
 17 	}
 18 }

Hopefully this will help someone else tackling a
similar problem.

Jonathan Cogley isthe CEO and founder of
thycotic, a .NET consulting company and ISV in Washington DC. thycotic has
just released
Thycotic Secret Server which is a secure web-based solution to both “Where is my Hotmail
password?” and “Who has the password for our domain name?”. Secret Server
isthe leader in secret management and sharing within companies and
teams.

Categories: .NET, ASP.NET

Automatic reporting of client-side script exceptions

December 7, 2005 6 comments

Error reporting is enormously powerful.
Knowing when your customers are seeing errors is the first step to improving
thequalityof your application.

In my previous
post
, I mentioned capturing client-side script exceptions while discussing a
dreaded hot fix that had to be made. You may have been wondering exactly
what I was talking about and if it might be useful for your
applications?

Hopefully you have already tapped into the
Application_Error method in global.asax.cs to publish exceptions (maybe to a log
file or as email). We tend to prefer getting exceptions in email because
it is a strong incentive to the development team to fix the problem. 🙂
However, Application_Error only catches server side exceptions which means that
many of the different browsers hitting your applicationmay be choking on
your client-side script and you wouldn’t even know! You may be thinking
that you can stop reading now because your application is intranet-based and
everyone is using Internet Explorer … not so! – different versions of Internet
Explorer can behave very differently with the same Javascript.

Our solution is to tap into the onerror event on
the window. You can have your own custom Javascript function fire anytime
an error occurs in client-side script. Now you need call back to the
server and cause an Application_Error call by throwing an exception on the
server side – this then allows your regular exception publishing to kick
in. We do this in the function below by calling back to the ASPX page
using a temporary Image with specific values in the QueryString
(onerror_message) – our base page class (you really should have your own
PageBase derived from System.Web.UI.Page but that is another discussion) then
checks for these messages and throws an exception if they are
present.

  1 <script language="javascript">
  2 // <!--
  3 // onerror
  4 window.onerror = window_onerror;
  5 function window_onerror(message,url,lineNumber) {
  6 	var queryString = '?onerror_message=' + escape(message)
  7 		+ '&onerror_url=' + escape(url)
  8 		+ '&onerror_lineNumber=' + lineNumber;
  9 	var onerrorImage = new Image();
 10 	onerrorImage.src = queryString;
 11 	return true;
 12 }
 13 // -->
 14
 15 

Please note that the user nevers sees the exception
message so it is silently reporting the errors without disrupting the user
experience.

Tip: You can
test your page for client-side script exceptions by going to your page and then
replacing the URL (in the browser window location textbox) with
javascript:CallABogusFunction(). This will make it call back to the server
but nothing will be apparent on the screen. You can also test your page
directly by adding ?onerror_message=xyz in the
QueryString.

Long live reporting *ALL* your
exceptions!

Jonathan Cogley isthe CEO and founder of
thycotic, a .NET consulting company and ISV in Washington DC. thycotic has
just released
Thycotic Secret Server which is a secure web-based solution to both “Where is my Hotmail
password?” and “Who has the password for our domain name?”. Secret Server
isthe leader in secret management and sharing within companies and
teams.

Categories: .NET, ASP.NET

Working around global.asax at runtime

December 6, 2005 Leave a comment

While this doesn’t classify as great development
practice, sometimes a well tested hotfix toa production site is just the
right thing to solve a client’s problem quickly. In our case, the problem
was too many emails being sent due to ClientScriptExceptions (our own custom
Exception that is thrown when a Javascript onerror event fires in the browser
… yes, we do some tricky stuff with an Image in Javascript to get the message
back to the server). Anyway, the exception is caught in global.asax.cs in
the Application_Error method.

So, how do we override this behavior at
runtime? Change the global.asax to the following:

  1 <%@ Application Codebehind="Global.asax.cs" Inherits="Thycotic.xxx.Web.Global" %>
  2 <script runat="server" language="C#">
  3 protected new void Application_Error(Object sender, EventArgs e)
  4 {
  5 	if (System.Web.HttpContext.Current != null)
  6 	{
  7 		Exception outer = HttpContext.Current.Server.GetLastError();
  8 		Exception inner = outer.InnerException;
  9 		Exception actualException = (inner == null) ? outer : inner;
 10 		if (!(actualException is Thycotic.Foundation.WebControls.ClientScriptException))
 11 		{
 12 			 Thycotic.Foundation.ExceptionManager.HandleApplicationErrorEvent();
 13 		}
 14 	}
 15 }
 16 	

Voila! Problem fixed without a recompile or binary
redeployment! Unfortunately, we hadn’t marked the original method as
virtual so we had to use “new” on the method signature – something we very
seldom use.

Hope you find this trick useful and never have to
use it! 🙂

Jonathan Cogley isthe CEO and founder of
thycotic, a .NET consulting company and ISV in Washington DC. thycotic has
just released
Thycotic Secret Server which is a secure web-based solution to both “Where is my Hotmail
password?” and “Who has the password for our domain name?”. Secret Server
isthe leader in secret management and sharing within companies and
teams.

Printable or ReadOnly pages in ASP.NET (code snippet)

September 22, 2005 2 comments

You have an ASP.NET page that is full of great controls, functionality, etc. but now you need to print it or render a “readonly” view of the page. Wouldn’t it be nice if there was a little ReadOnlyproperty that you could flip to true on the page and that was it? Well … there isn’t. However with a little recursive code, you can achieve the same effect.

This code snippet is provided to help a few other soulswith our same need:
DISCLAIMER: This code is not perfect but does work as intended and is unit tested (in our application).

Click here for code snippet

The basic approach is loop through all Controls from a certain control down (Page if you choose, since Page is-a Control) and make certain control replacements based on the control that is being evaluated.

The use of Reflection can probably be avoided entirely with a bit of refactoring and use of interfaces instead. Using the string representation of the type name of the Control is a little ugly and could be improved. Also note that this code makes certain controls not visible such as Button which may not be desirable. Another approach is to derive your own controls from the base controls and provide a “ReadOnly” rendering – this is probably morework than a simple recursive loop as above.

Comments are welcome.

Jonathan Cogley isthe CEO and founder of thycotic, a .NET consulting company and ISV in Washington DC. Our product, myclockwatcher.comis a time andexpense tracking system specializedfor billable professionals built on ASP.NET, C# and SQL Server using Test Driven Development.

Categories: .NET, ASP.NET