Sorted By: Month (3) and Year (2011)

We Love .NET 4 - Clean Web Control IDs with ClientIDMode Property to Static and Predictable

In this blog post, we will see how ClientIDMode property of Web Controls makes our lives easier. Also, we will demonstrate couple of scenarios on how it works...
2011-03-24 17:58
Tugberk Ugurlu


If you want, you could directly download the source code which is used in this blog post as example and skip the reading Smile. Source code is on ;

http://cid-0ee89cb310fe3603.office.live.com/self.aspx/Programming/WeLoveNet4^_1.rar

One of the things that every JavaScript programmers hate about ASP.NET is Web Control IDs. When we use Master Page or any of Data Controls for displaying data (there are other things which fit in this category but for the sake of less talking, I skipped them), the id of the web controls’ values are generated by concatenating the ID values of each parent naming container with the ID value of the control. This thing screws up the id of the control. As you can see on below source view;

image_thumb[5]

This also makes it hard to write JavaScript (nowadays, JavaScript is also known as JQuery which is kind of bizarre because JQuery is a JavaScript library Smile) codes when we want to bind the code to a control. Of course, it is not impossible to accomplish that on ASP.NET. There are a few ways of doing that on ASP.NET;

  1. One of the ways is to create a JS function and bind the control to that function inside the DOM. For instance, let’s say we have System.Web.UI.Controls.Button control on our web form and we would like to fire a JS function on click of this button. User creates the JS function and bind the control to the function by putting the function name on OnClientClick property of the Button control. I do not recommend this way. Binding the JS code to DOM elements directly is sloppy. 
  2. Other way is to bind the JS code to a Web Control by getting the name of the control with code blocks (often called Code Nuggets by members of the Visual Web Developer team). We’ll get that option on our following example latter.

With .NET Framework v4, we have been introduced with a new property of Web Controls called ClientIDMode. This little thing is now making our lives easier. ClientIDMode gets or sets the algorithm that is used to generate the value of the ClientID property.

ClientIDMode’s value type is enum and it has 4 values. The default value of ClientIDMode for a page is Predictable. The default value of ClientIDMode for a control is Inherit.

You can get more information on Control.ClientIDMode property from offical MSDN document :

http://msdn.microsoft.com/en-us/library/system.web.ui.control.clientidmode.aspx

I think better way of understanding this is by demonstrating a scenario. On the following example, our goal is to fire a JS function with on click event of a button control. Let’s see how this little feature fits in our lives.

OldFashionWay.aspx

We are assuming that we are working on .NET 3.5 here. So, we do not have the ability to use ClientIDMode feature. What do we do then? Following OldFashionWay.aspx web form code shows us how we can accomplish that;

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">

    <title>We Love .NET 4</title>

    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>

    <script type="text/javascript">

        $(document).ready(function () {
            $("#<%= button1.ClientID  %>").click(function () {
                alert('textbox1.Text : ' + $("#<%= textbox1.ClientID  %>").val());
            });
        });

    </script>

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">

        <div>
        
            <asp:TextBox runat="server" ID="textbox1" />  <asp:Button Text="Submit" ID="button1" runat="server" />

        </div>

</asp:Content>

As you can see inside the script tag, we use Code Nuggets to determine the id of the web controls. Here is the result;

image_thumb[7]

image_thumb[12]image_thumb[10]

This way works just fine but only inside the .aspx files. When we want to get the JavaScript code out of here, put it on a separate .js file and reference it inside the .aspx page, you will certainly fail! This is because of the fact that ASP.NET framework do not apply any special rendering on.js files as it does on .aspx, .ashx or any other ASP.NET specific file types.

ClientIDMode.aspx

As we mentioned earlier, we have been introduced with ClientIDMode property for Web Controls on .NET Framework v4. Let’s see how we accomplish the above scenario on .NET Framework v4. Here is ClientIDMode.aspx file code;

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">

    <title>We Love .NET 4</title>

    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>

    <script type="text/javascript">

        $(document).ready(function () {

            $("#button1").click(function () {
                alert('textbox1.Text : ' + $("#textbox1").val());
            });

        });

    </script>

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">

    <div>
        
        <asp:TextBox runat="server" ID="textbox1" ClientIDMode="Static" />  
        <asp:Button Text="Submit" ID="button1" runat="server" ClientIDMode="Static" />

    </div>

</asp:Content>

As you can notice here, we have set ClientIDMode property of TextBox and Button control to Static. What does that mean? When we set the ClientIDMode to Static, the ClientID value is set to the value of the ID property. If the control is a naming container, the control is used as the top of the hierarchy of naming containers for any controls that it contains. Let’s view the rendered html source code;

image_thumb[14]

The id of the controls are the same as we determined. Perfect!

ClientIDMode_SeperateJSFile.aspx

Let’s make our html file unobtrusive. ClientIDMode_SeperateJSFile.aspx file’s source code;

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">

    <title>We Love .NET 4</title>
    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
    <script src="Scripts/ClientIDMode.js" type="text/javascript"></script>

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">

    <div>
        
        <asp:TextBox runat="server" ID="textbox1" ClientIDMode="Static" />  
        <asp:Button Text="Submit" ID="button1" runat="server" ClientIDMode="Static" />

    </div>

</asp:Content>

What we do here is to get the JS code out of the .aspx file and put it inside a separate .js file. This way we could use the same file for other pages and we will accomplish to make ourselves DRY (Don’t Repeat Yourself). We are unable to do that on .NET 3.5 as we mentioned above. ClientIDMode.js is no different than the JS code we used before. Here is the content of ClientIDMode.js;

$(document).ready(function () {

    $("#button1").click(function () {
        alert('textbox1.Text : ' + $("#textbox1").val());
    });

});

Pretty awesome Smile

ClientIDMode_ForEntirePage.aspx

Assuming that we have a large page content and it will make it hard to set ClientIDMode for every Web Control. ASP.NET team also have thought that. We can set the ClientIDMode value for a page in the @ Page directive. Only we need to do is to set ClientIDMode property on <%@ Page … %> section;

<%@ Page 
        Title="" 
        Language="C#" 
        ClientIDMode="Static" 
        MasterPageFile="~/Site1.Master" 
        AutoEventWireup="true" 
        CodeBehind="ClientIDMode_ForEntirePage.aspx.cs" 
        Inherits="WeLoveNet4_1.WebForm22" %>

After this configuration, you do not need to set ClientIDMode value for every control.

Also, we can set the ClientIDMode value for all pages in a Web site by setting the pages element in the site's Web.config file. Example code for Web.config;

<configuration>
  
    <system.web>
        <pages clientIDMode="Static"></pages>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>

</configuration>

ClientIDMode_InsideData-Bound_Controls.aspx

On data-bound scenarios, there is another property that we can make use of for ListView control : ClientIDRowSuffix. ClientIDRowSuffix gets or sets the name of the data field whose value is used to uniquely identify each data row of a ListView control when the ClientIDMode property is set to Predictable.

Let’s see our example. here is the ClientIDMode_InsideData-Bound_Controls.aspx file’s code;

<html xmlns="http://www.w3.org/1999/xhtml">

<head id="Head1" runat="server"></head>

<body>

    <asp:ListView ID="ListView1" ClientIDMode="Predictable" ClientIDRowSuffix="LanguageID"  runat="server" >

        <ItemTemplate>
            <li>
                <asp:Label Text='<%# Eval("Name") %>' ID="namelabel" runat="server" /> : 
                <asp:Label Text='<%# Eval("Rating") %>' ID="ratinglabel" runat="server" />
            </li>
        </ItemTemplate>

        <LayoutTemplate>
            
            <div ID="itemPlaceholderContainer" runat="server">
                <ul ID="itemPlaceholder" runat="server" />
            </div>
            
        </LayoutTemplate>

    </asp:ListView>

</body></html>

As it is above, we have set ClientIDMode of ListView control to Predictable and ClientIDRowSuffix of ListView control to LanguageID which is the ID field of our datasource. Some of you might wonder where the datasource is. I made a List of ProgrammingLanguages and bound it to ListView1 as you can see on the below code;

    public partial class ClientIDMode_InsideData_Bound_Controls : System.Web.UI.Page {

        public class ProgrammingLanguages {

            public int LanguageID { get; set; }
            public string Name { get; set; }
            public int Rating { get; set; }

        }

        protected void Page_Load(object sender, EventArgs e) {

            List<ProgrammingLanguages> _list = new List<ProgrammingLanguages>();

            _list.Add(new ProgrammingLanguages {LanguageID = 10, Name="C#", Rating=10 });
            _list.Add(new ProgrammingLanguages {LanguageID = 20, Name = "Visual Basic", Rating = 6 });
            _list.Add(new ProgrammingLanguages {LanguageID = 30, Name = "F#", Rating = 7 });
            _list.Add(new ProgrammingLanguages {LanguageID = 45, Name = "Java", Rating = 8 });

            ListView1.DataSource = _list;
            ListView1.DataBind();

        }
    }

When we view the source code of the rendered page, we will see that id of the controls are predictable.

image_thumb[16]

I hope that this article gives you an idea on how you can make your application better with this new feature of ASP.NET.

Happy coding Smile

File By File Deployment Process with MSDeploy Inside Visual Studio

Have you ever used 'MSDeploy' inside Visual Studio 2010 and wished a nice process bar while publishing a web application? There is even a better way!
2011-03-05 08:32
Tugberk Ugurlu


image

Deployment of your web application is not hard anymore. It is so much easier than before with 'MSDeploy'. MSDeploy was introduced to us with Visual Studio 2010. It takes all the application and publish it how we want.

I am not going to explain what MsDeploy is and how it works. This is bot the topic here. I assumed that you are reading this post because you have had a least one or two experience with MSDeploy inside Visual Studio 2010.

When we are publishing an application with one click publish button, you probably noticed a little green world icon with coming and going tiny things on the left bottom side. That think is showing the process of your publishing but not so much informative. I thought that would be cool to view the remaining time of the process but Visual Studio has a lot better feature which I didn’t know until last night! Indeed, we have a chance to view the process file by file from output window of visual studio 2010 while publishing your application. That is pretty darn cool. But how we can configure this feature so that we could be able to view that.

imageWe need to go over to Tools > Options. Then expend the Projects and Solution section from the list on the window. You will find Build and Run section under that which will give you a window which will look like as it is here on the left. You notice that there is an option called 'MsBuild project build output verbosity'. There are five options there and it is set to Minimal by default. I changed it to Normal which is enough for our purpose here.

Save your settings and then expend the output window. You can start your publishing process now and you will see which file is now being deployed by MSDeploy as you can also see on the above screenshot. Yes, awesome… Smile Now, think about twice before using an FTP client again Smile

Local IIS 7.0 - CS0016: Could not write to output file / Microsoft.Net > Framework > v4.0.30319 > Temporary ASP.NET Files

Solution to an annoying error message! You are getting 'Could not write to output file 'c:\Windows\Microsoft.NET\Framework\....' message? You are at the right place.
2011-03-05 08:18
Tugberk Ugurlu


This week I went nuts over my local IIS. I have never swore to a machine that much in my whole life. I am sure of that! The problem is not that big and probably not worth to be written on a blog post I am going to write it anyway because the solution was hard to find on the internet. Maybe this post will help you to fix the problem as I did and you will stop swearing to you machine as I did Smile

Let’s get to the point. I am no IIS guy! Seriously!  The so called Cassini (the tiny web server which pops up when you run a web application on Visual Studio) was so enough for me for over 2 years. But no more enough. I figured that IIS can not be ignored by me anymore. How can I get that point? That’s not the issue here. The issue is that I tried to run an ASP.NET MVC 3.0 application under my local IIS 7.0 and got a very annoying error. Which is;

Compiler Error Message: CS0016: Could not write to output file 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\62d43c41\27d749ca\App_Code.7lodcznm.dll' – 'Access denied.'

imageTemporary ASP.NET Files folder (c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files) was the the one with the problem here. First, I thought that the problem is related to security permissions on the folder and I was right.

I right clicked on the Temporary ASP.NET Files folder and go to the security tab. I noticed that there is user called IIS_IUSRS and that guy has the full control permission. But apparently that was not enough.

The Temporary ASP.NET Files  and C:\Windows\temp folders should have IIS_WPG and NETWORK SERVICE users with the full control permission. I have no idea why C:\Windows\temp folder needs that but I have no effort left to try to find that. Instead, I am writing a blog post about the problem. Maybe latter I will get to that and figure it out, too Smile

Once you applied those setting, restart your IIS and try to run your application again. The error should be gone by now.

I suffered a lot by trying to find the right method for the problem and I hope you didn’t have to go through hell over this.

Hope this helps Smile

Tags