Jon's Blog

.NET Development & More

ASP.NET AJAX UpdatePanel + jQuery UI Dialog

clock May 3, 2011 15:21 by author 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>


LINQ: Complicated Advanced Search with Dynamic Where Clause

clock January 24, 2011 13:32 by author 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.
}

 



ASP.NET: Improving Your Error Logging & Handling

clock January 24, 2011 11:05 by author 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.



ASP.NET AJAX: Return to Top of Page After Partial Postback

clock December 15, 2010 10:49 by author 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);" />


How to Use FreeTextTable

clock September 1, 2010 10:41 by author 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.



ASP.NET: Fun with Paths and Directories

clock August 19, 2010 15:02 by author 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

Property/Method and Description Result
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);


Hiding ASP.NET Ajax Modal Popup Dialog Using JavaScript

clock July 16, 2010 13:22 by author 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>


ASP.NET AJAX: UpdateProgress Displaying Behind DropShadowExtender Control

clock June 15, 2010 10:39 by author 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>


Visual Studio: System.Web.AspNetHostingPermission Failed

clock May 20, 2010 14:09 by author 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.



Removing Control From Tab Order

clock April 27, 2010 15:33 by author 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" />