Technology Toolbox

Your technology Sherpa for the Microsoft platform

Jeremy Jameson - Founder and Principal

Search

Search

DataNavigateUrlFormatString Does Not Allow "javascript:"

Note
This post originally appeared on my MSDN blog:

Since I no longer work for Microsoft, I have copied it here in case that blog ever goes away.

I encountered an interesting bug last Friday with the ASP.NET HyperLinkField control. To understand the scenario, think of the typical "view detail" feature when showing summary data in a table. In other words, you want to provide users the ability to click a cell in a table (e.g. a GridView control) in order to see more information.

I've implemented this scenario before, so I was a stumped when I couldn't get it to work right away. However, this time the scenario was a little different because we want to display a popup window to an external site. Also note that several visual properties of the popup window need to be specified for our application -- such as the width and height of the window, as well as hiding the menu bar, status bar, etc.

In other words, we need the links in the table to actually call a JavaScript function instead of specifying a simple URL.

My initial attempt was to specify something like :

<asp:GridView ID="summaryGrid" runat="server"
    AutoGenerateColumns="False"
    ...>
    ...
    <Columns>        
        <asp:HyperLinkField DataNavigateUrlFields="Id"
           DataNavigateUrlFormatString="javascript:ShowItemDetail({0})"
           DataTextField="CreateTime"
           DataTextFormatString="{0:ddd MMM dd HH:mm}"
           HeaderStyle-CssClass="dateColumn"
           HeaderText="Date" />  
       ...
    </Columns>
</asp:GridView>

Note that ShowItemDetail is a JavaScript function that simply calls window.open (specifying the URL as well as additional "feature" parameters such as the window width and height).

Unfortunately, if you specify something like "javascript:ShowItemDetail({0});" in DataNavigateUrlFormatString, you will find that ASP.NET renders an anchor element with no href attribute (e.g. <a>Mon Oct 26 08:23</a>) -- which obviously doesn't work. This appears to be "by design" -- in order to "mitigate against cross-site scripting attacks."

Refer to the following for more detail:

asp:GridView does not render HyperLinkField when a colon (:) is included in the DataNavigateUrlFormatString. 2007-06-05.

To workaround this, use a TemplateField instead:

<asp:GridView ID="summaryGrid" runat="server"
    AutoGenerateColumns="False"
    ...>
    ...
    <Columns>
        <%-- HACK: Ideally, we would just use an asp:HyperLinkField,
        but there's a bug when specifying "javascript:" in the
        DataNavigateUrlFormatString:

        https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=102300

        As a workaround, use a TemplateField instead. --%>
        <asp:TemplateField>
           <HeaderTemplate>Date</HeaderTemplate>
           <HeaderStyle CssClass="dateColumn" />
           <ItemTemplate>
               <a href='javascript:ShowItemDetail(<%# Eval("Id")%>)'>
                   <%# Eval("CreateTime", "{0:ddd MMM dd HH:mm}") %>
               </a>
           </ItemTemplate>
        </asp:TemplateField>
        ...
    </Columns>
</asp:GridView>

Or, if you are really paranoid about the performance impact of using reflection in the DataBinder.Eval method, you can use strongly typed objects instead:

<asp:GridView ID="summaryGrid" runat="server"
   AutoGenerateColumns="False"
   ...>
   ...
   <Columns>
      <%-- HACK: Ideally, we would just use an asp:HyperLinkField,
      but there's a bug when specifying "javascript:" in the
      DataNavigateUrlFormatString:
        
      https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=102300
        
      As a workaround, use a TemplateField instead.
      --%>
      <asp:TemplateField>
         <HeaderTemplate>Date</HeaderTemplate>
         <HeaderStyle CssClass="dateColumn" />
         <ItemTemplate>
             <a href='javascript:ShowItemDetail(<%# ((Fabrikam.Demo.Integration.Incident)Container.DataItem).Id %>)'>
                 <%# ((Fabrikam.Demo.Integration.Incident)Container.DataItem).CreateTime.ToString("ddd MMM dd HH:mm") %>
             </a>
         </ItemTemplate>
      </asp:TemplateField>
      ...
   </Columns>
</asp:GridView>

Of course, if you choose to go the strongly-typed route, you will need to reference the assembly containing your custom business objects. For example:

<%@ Assembly Name="Fabrikam.Demo.Integration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=786f58ca4a6e3f60" %>

Comments

  1. # re: DataNavigateUrlFormatString Does Not Allow "javascript:"

    January 26, 2011 6:05 AM
    GB

    Nice. I've seen some work-arounds using code-behind, but your approch using Eval() is cleaner.

    Thanks

  2. # re: DataNavigateUrlFormatString Does Not Allow "javascript:"

    November 10, 2014 7:06 AM
    Jerry Cote
    Gravatar
    Thanks Jeremy! I know this is an old post but it just helped me today. Perfect solution

Add Comment

Optional, but recommended (especially if you have a Gravatar). Note that your email address will not appear with your comment.
If URL is specified, it will be included as a link with your name.

To prevent spam from being submitted, please select the following fruit: Pear

Grapes
Strawberry
Pear
Cherries
Watermelon
Apple
 
Please add 5 and 7 and type the answer here: