
May 3, 2011 15:21 by
Jon
The jQuery UI Dialog does not seem to play nicely with the ASP.NET AJAX UpdatePanel. After doing a partial page postback using an UpdatePanel the jQuery UI Dialog div would no longer function. Thanks to Stack Overflow and some blog posts I discovered that you need to add some code to hook into the ASP.NET AJAX JavaScript pageLoaded event and this will reinitialize the jQuery UI Dialog div every time. We also need to append the div to the form element so that any ASP.NET buttons on the div will post back to our page. In the following JavaScript snippet my jQuery modal dialog div has an ID of "myDiv". Also, in this example we are setting up the dialog to be modal and autoOpen equal to false.
<script type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function (evt, args) {
var myDiv = $("#myDiv").dialog({ autoOpen: false, modal: true, open: function (type, data) {
$(this).parent().appendTo("form");
}
});
});
</script>

January 24, 2011 13:32 by
Jon
Recently I was working a project that needed a very complicated Advanced Search. I had to dynamically build the Where clause. The tricky part for this project was that the Where statement would be using both SQL ORs and ANDs. Using LINQ, the prior way I was building dynamic Where statements was just using ANDs. Basically I was just adding AND statements if they needed to be included in the query. However, this time I needed to include a clause where the user could pick one or more of an item from a list. Thankfully, I discovered the PredicateBuilder class (part of the LINQKit library), which allows you to dynamically build a Where statement with both ANDs and ORs.
I have put together a very simple and crude example to summarize what I did. Please excuse the simplicity of the code below. Usually I would write the code much cleaner, but I wanted to keep it simple for readability.
So let's say you have an advanced restaurant search form. The user must select one or more cuisine types and then can optionally choose the city, state, country where the restaurant is located. The form might look like this:

The query I was building in my project was more complicated than this, but you get an idea of how complicated these kinds of queries can get. Here's some example SQL of what LINQ might need to generate.
SELECT *
FROM Restaurant
WHERE City='Dallas'
AND State='TX'
AND(Mexican=1 OR German=1 OR Italian=1)
With the PredicateBuilder class this is totally doable. Following is the button click event for the Search button where you can get an idea of how to use PredicateBuilder. First, you build the inner OR statement and then you can add that to your full Where clause at the end. This is just a quick example, so go read the documentation for a better understanding of how PredicateBuilder works.
using LinqKit;
protected void btnSearch_Click(object sender, EventArgs e)
{
// Create Inner Where Statements
var innerWhere = PredicateBuilder.False<Restaurant>();
if (cbMexican.Checked)
innerWhere = innerWhere.Or(q => q.Mexican);
if (cbItalian.Checked)
innerWhere = innerWhere.Or(q => q.Italian);
if (cbChinese.Checked)
innerWhere = innerWhere.Or(q => q.Chinese);
if (cbGerman.Checked)
innerWhere = innerWhere.Or(q => q.German);
if (cbAmerican.Checked)
innerWhere = innerWhere.Or(q => q.American);
// Build Full Where Statement
var outerWhere = PredicateBuilder.True<Restaurant>();
if (!string.IsNullOrEmpty(ddlCountry.SelectedValue))
outerWhere = outerWhere.And(q => q.Country == ddlCountry.SelectedValue);
if (!string.IsNullOrEmpty(ddlState.SelectedValue))
outerWhere = outerWhere.And(q => q.State == ddlState.SelectedValue);
if (!string.IsNullOrEmpty(txtCity.Text.Trim()))
outerWhere = outerWhere.And(q => q.City == txtCity.Text.Trim());
// Add the inner OR query to the Where statement
outerWhere = outerWhere.And(innerWhere);
var query = from r in myDC.Restaurants.Where(outerWhere)
select r;
// Bind query to ListView, GridView, etc.
}

January 24, 2011 11:05 by
Jon
One of the first things I like to setup when I am creating a new site is a customized error page and error logging. To log all unhandled errors on your site you can add some code to the Application_Error event of your Global.asax file. What I do is to grab the exception and then I use a static method of a helper class I have in my class library. I pass the name of the web application where the error occurred and the exception itself. In the helper method I can then extract the details I need from the exception and log it to a database table.
Global.asax.cs:
public const string APP_NAME = "Name of My App";
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError().GetBaseException();
SiteErrorLog.LogError(APP_NAME, ex);
}
Next, in the web.config you can setup your site so the user sees a nice, customized error page instead of the default ASP.NET error page. Under the <system.web> node, add the following:
<customErrors mode="RemoteOnly" defaultRedirect="ErrorPage.aspx"></customErrors>
Now when your site is hit from a remote client (RemoteOnly) and an unhandled error occurs they will be redirected to the page you created (ErrorPage.aspx). This is much nicer for the user of your site.

December 15, 2010 10:49 by
Jon
After an AJAX partial postback you may need to return to the top of your ASPX page to display an error message, etc. Here is one way that I have done it. You can add the JavaScript function below to your ASPX page and then call the method when needed in your code-behind by using the ScriptManager.RegisterClientScriptBlock method.
ASP.NET C# Code-behind:
ScriptManager.RegisterClientScriptBlock(this, Page.GetType(),
"ToTheTop", "ToTopOfPage();", true);
JavaScript:
<script type="text/javascript">
function ToTopOfPage(sender, args) {
setTimeout("window.scrollTo(0, 0)", 0);
}
</script>
You can also just JavaScript to scroll to the top of the page by using the OnClientClick property of your button. But this will cause this behavior to occur every time the button is clicked and not just when you want it to happen. For example:
<asp:Button id="bntTest" runat="server"
Text="Test" OnClick="btn_Test"
OnClientClick="javascript:window.scrollTo(0,0);" />

September 1, 2010 10:41 by
Jon
The FreeTextTable function in SQL Server is very useful when you need to search a column for words, phrases, etc. FreeTextTable will return a table that you can join on. It also returns the Rank of the matches so you can order the most relevant matches at the top.
In the example below I am searching the Keywords column of the MyTable table using the @Keywords passed into the stored procedure. I am then ordering them by Rank so the highest matches show up first.
CREATE PROCEDURE [dbo].[FreeTextSample]
@Keywords [varchar](1000) = ''
WITH EXECUTE AS CALLER
AS
BEGIN
SET NOCOUNT ON;
SELECT myTable.MyPrimaryKeyID,
myTable.Title,
myTable.Description
FROM MyTable myTable(nolock)
INNER JOIN FreeTextTable(dbo.MyTable, Keywords, @Keywords) AS searchTable
ON myTable.MyPrimaryKeyID = searchTable.[KEY]
ORDER By searchTable.[RANK] DESC
END
GO
One thing to note is that LINQ does not contain an equivalent keyword for FreeTextTable. So what I did was to create a new method on my DataContext that returns the results of the stored procedure. See my post here for further details on how to do this.

August 19, 2010 15:02 by
Jon
In the following table the page executing the code is at the following physical location on my machine:
C:\Users\me\Documents\Visual Studio 2010\Projects\TestStuff\TestStuff\Nested\Paths.aspx
| Request.ApplicationPath
Gets the root virtual path.
|
/TestStuff |
| Request.CurrentExecutionFilePath
Gets the virtual path to the current file. Same as Request.Path and Request.FilePath.
|
/TestStuff/Nested/Paths.aspx |
| Request.CurrentExecutionFilePathExtension
Gets the file extension of the current file.
|
.aspx |
| Request.FilePath
Gets the virtual path to the current file. Same as Request.CurrentExecutionFilePath and Request.Path.
|
/TestStuff/Nested/Paths.aspx |
| Request.MapPath("")
Gets the full physical path to the current directory. Seems to be the same as Server.MapPath("").
|
C:\Users\me\Documents\Visual Studio 2010\Projects\TestStuff\TestStuff\Nested |
| Request.Path
Gets the virtual path to the current file. Same as Request.CurrentExecutionFilePath and Request.FilePath.
|
/TestStuff/Nested/Paths.aspx |
| Request.PhysicalApplicationPath
Gets the physical path to the root directory. Seems to be the same as AppDomain.CurrentDomain.BaseDirectory.
|
C:\Users\me\Documents\Visual Studio 2010\Projects\TestStuff\TestStuff\ |
| Request.PhysicalPath
Gets the full physical path to the current file.
|
C:\Users\me\Documents\Visual Studio 2010\Projects\TestStuff\TestStuff\Nested\Paths.aspx |
| AppDomain.CurrentDomain.BaseDirectory
Gets the physical path to the root directory. Seems to be the same as Request.PhysicalApplicationPath.
|
C:\Users\me\Documents\Visual Studio 2010\Projects\TestStuff\TestStuff\ |
| Server.MapPath("")
Gets the full physical path to the current directory. Seems to be the same as Request.MapPath("").
|
C:\Users\me\Documents\Visual Studio 2010\Projects\TestStuff\TestStuff\Nested |
Also, if you are joining a directory to a file/path I recommend using the Path.Combine method found in the System.IO namespace. Here is an example:
using System.IO;
string fileName = "MyFile.pdf";
string fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
fileName);

July 16, 2010 13:22 by
Jon
Following is an easy way to hide the modal popup dialog extender from the AJAX control toolkit using JavaScript. The key is to set a BehaviorID on the ModalPopupExtender. Then you can use this ID to call the hide() method via Javascript like this:
function HideModal() {
$find('modalPopupBehavior').hide();
}
In the full example below I am closing the modal popup dialog box when the user clicks on a link.
Full ASPX example:
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxtk" %>
<!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">
<title>My Page</title>
<link href="css/Test.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="aspNetForm" runat="server">
<asp:ScriptManager ID="scriptMan" runat="server" />
<script type="text/javascript" language="javascript">
function HideModal() {
$find('modalPopupBehavior').hide();
}
</script>
<asp:UpdatePanel ID="upnlMain" runat="server">
<ContentTemplate>
<div>
<ajaxtk:ModalPopupExtender ID="modalPopup" runat="server"
BehaviorID="modalPopupBehavior"
TargetControlID="btnPopup" PopupControlID="pnlPopup">
</ajaxtk:ModalPopupExtender>
<asp:Button ID="btnPopup" runat="server" Text="Show Popup" />
<asp:Panel ID="pnlPopup" runat="server" CssClass="modalPopup"
style="width: 715px; display: none;">
<div>
<p>
<a href="http://www.jonathanjungman.com/blog/"
target="_blank" onclick="HideModal()">Hide Modal</a>
</p>
</div>
</asp:Panel>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>

June 15, 2010 10:39 by
Jon
I ran into an issue the other day where my UpdateProgress control (an animated GIF) would display behind any div that was using the DropShadowExtender control from the AJAX Control Toolkit. In order to fix this issue I set the CSS class on the div of the UpateProgress to "postion: fixed" and the "z-index" to an arbitrarily high number.
This is before the CSS change. Notice the animated GIF just peeking out from the end of the drop shadow at the bottom right of this image.

And here is what it looks like after the CSS change. The animated GIF now displays properly in front of the div using the drop shadow.

CSS:
div.divProgress { z-index: 1001; position: fixed; }
ASPX:
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxtk" %>
<ajaxtk:DropShadowExtender id="dse" runat="server" TargetControlID="divPanel"
TrackPosition="true" />
<div id="divPanel" runat="server" class="Box">
<div class="BoxHeader">This Is My Header</div>
<div>
<p>Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.
Text here. More Text. Whoa. Text here. More Text. Whoa. Text here. More Text. Whoa.</p>
<p>
<asp:Button ID="btnDoSomething" runat="server" Text="Do Something"
onclick="btnDoSomething_Click" />
</p>
</div>
</div>
<ajaxtk:AlwaysVisibleControlExtender ID="AlwaysVisibleControlExtender" runat="server"
TargetControlID="updateProgress" HorizontalSide="Center" VerticalSide="Middle" />
<asp:UpdateProgress ID="updateProgress" runat="server" DynamicLayout="true" >
<ProgressTemplate>
<div class="divProgress" id="divProgress" runat="server" align="center">
<img src="~/images/red_rotation.gif" id="imgUpdateProgress" runat="server" alt="Please Wait..." />
</div>
</ProgressTemplate>
</asp:UpdateProgress>

May 20, 2010 14:09 by
Jon
I got this error in Visual Studio when I was running one of our projects on a new development machine where I had just recently installed a fresh copy of Visual Studio 2008. After installing the Microsoft .NET SDK this error went away. Hopefully this post helps someone else out there.

April 27, 2010 15:33 by
Jon
This one is simple but nice to know. To remove a control from the tab order you can just set its TabIndex to -1. I thought there might be a "turn tabbing off" property, but this seems to be the easiest way.
<asp:CheckBox ID="myCB" runat="server" Text="MyCB" TabIndex="-1" />