Displaying articles with tag asp.net

Set a property of a server tag dynamically

Posted by gabriel, Sun Sep 28 11:49:00 UTC 2008

Setting a property of a server tag is pretty standard stuff:


<asp:TextBox ID="TextBox1" runat="server" Text="My name is Gabriel" />

Now, what if you want to use a class to set the value?


<asp:TextBox ID="TextBox1" runat="server" Text='<%= DateTime.Now %>' />

This will give you an error like this:

Server tags cannot contain <% ... %> constructs

If you ever need to solve this kind of problem I found a very interesting solution in the Infinites Loop Blog

It’s a very clever solution to use the Expression Builders, introduced in the Asp.Net 2.0 feature, to let you execute your custom code within the server tags.

0 comments | Filed Under: | Tags: asp.net

Asp.Net: UpdatePanel concurrent requests

Posted by gabriel, Tue Aug 05 12:32:00 UTC 2008

Yesterday I was coding the infrastructure to start a thread in the server that would take too long to finish and would timeout the browser. The idea is that you could start a thread to run your long operation and let the server return the response to the browser. In order to give some feedback to the user I would query the server from time to time to check on the progress of the operation.

Everything was going great but then someone said the client wanted to be able to cancel the task running on the server. At first though it would not mess up what I had done already. The thing is that if the server was already querying the status of the task and I tried to cancel at the same time I would get an error.

Long story short, you have problem when the UpdatePanel makes multiple requests concurrently. When you do this the last request being executed wins. I looked around and found an interesting solution to this problem.

http://geekswithblogs.net/rashid/archive/2007/08/08/Asp.net-Ajax-UpdatePanel-Simultaneous-Update—-A-Remedy.aspx

What this guy did was to intercept the asyn requests and enqueue them so they are only done one at a time. Of all the things I found on the Internet this was the most interesting solution.

There is also an interesting solution in the Asp.Net site that allows you to define on among several UpdatePanel that gets precedence over the others. So, if one request is being executed and the preferred UpdatePanel trying to execute the other one is canceled. See it here

1 comment | Filed Under: Tips and Tutorials | Tags: asp.net

Add Controls Dynamically - Part 5

Posted by gabriel, Sun Jul 27 19:09:00 UTC 2008

In parts 1 to 4 I have talked about creating dynamic controls and adding them to the page. I haven’t talked about a important aspect of Asp.Net that is very important for any developers and specially if you are dealing with dynamic controls. So in this article I’m going to talk about the Asp.Net Life cycle.

Related posts:

Asp.Net Life Cycle

As I said in previous articles the state of the page or any of it’s components is not stored on the sever. Everything is stored on the page. This is due to the characteristics of HTTP protocol which is stateless. Having this in mind, every time there is a postback the structure of the page is recreated so that you can have access to the controls through code. I’m not sure if I made myself clear so here another way to put it:

HTML is HTML and that is it. When you look at the page in the browser all there is is HTML, there is no C# or VB.Net. Only when the page is submitted to the server is that the HTML is going to be read transformed in server side controls. The programmer then uses these server side controls to manipulate the controls. At the end this controls will render HTML again which will be sent to the page.

Ok, so why is this important? Well, the process of creating the server side code from the HTML happens in several stages which fire events that let you interact with the components in the right moment.

The life cycle has a lot of stages but the ones we are interested in are the Initialization and Load. For more details on all stages check out MSDN

Initialization

In this stage the controls available on the page (not the ones created dynamically) become available. The ViewState has not been retrieved however and therefore the control values cannot be loaded in the controls. The postback data is also not available at this stage.

The Load stage has three events to help the programmer:
  1. PreInit
  2. Init
  3. InitComplete

In the PreInit event the controls don’t even exist yet. They have not been created.

If you set a property like the Text of a TextBox in these events this value will be lost in future stages when the control is loaded. If you want to use these events you need to declare the following methods in your code:


    void Page_PreInit(object sender, EventArgs e)
    {

    }

    void Page_Init(object sender, EventArgs e)
    {

    }

    void Page_InitComplete(object sender, EventArgs e)
    {

    }

Load

This is an important stage for us because it is here that the values of the controls are loaded. Before this stage you might have the controls but it’s values have are not there yet.

The Load stage has three events to help the programmer:
  1. PreLoad
  2. Load
  3. LoadComplete

We have used the Page_Load event in our previous examples to create our dynamically created controls. The thing to watch is that when these controls are created they don’t have it’s values from the page loaded yet. If you want to get the values from the controls you can only do it in the Page_LoadComplete event. Only then all the values of the controls will be loaded.

You can test this using creating the method for each of these events and using the debugger to check the controls we the event is hit.


    void Page_PreLoad(object sender, EventArgs e)
    {

    }

    void Page_Load(object sender, EventArgs e)
    {
        //when the user first enters the page set the count as zero
        if (!IsPostBack)
        {
            ViewState["count"] = 0;
        }
        //on every subsequent postback, check the control count
        //and recreated all the controls
        else
        {
            int controlCount = (int)ViewState["count"];
            for (int i = 0; i < controlCount; i++)
            {
                //notice that now we pass the i as parameter
                createDynamicControls(i);
            }
        }
    }

    void Page_LoadComplete(object sender, EventArgs e)
    {

    }

Notice that I have used the Load event defined in the previous articles but the methods for the other events are new. If you set a breakpoint and use the Watch to inspect the controls you can see when the values have been loaded.

Ok, so if you need to create the controls you do it where we’ve been doing up to now: In the Page_Load

If you need to get the values from these controls right after you loaded them you need to wait for the Page_LoadComplete event.

Well, I hope this info was useful.

1 comment | Filed Under: Tips and Tutorials | Tags: asp.net

Add Controls Dynamically - Part 4

Posted by gabriel, Mon Jul 21 21:59:00 UTC 2008

The part 3 of this series was getting a bit long for my taste so I decided to break it in 2. Here we’ll continue dealing with the controls added dynamically to our page only now we’re going to access them by ID.

Related posts:

Naming the controls

By now you have noticed that we haven’t explicitly set the ID of any of our controls. Of course the controls have ID’s but they are defined automatically by the Asp.Net framework when the controls are instantiated. The reason this works is because the framework will create the names consistently the same, again and again as long as you create the controls always in the same order (we are doing that).

It is this automatically naming feature that allows our components to keep their state between requests. When the page is submitted all of the controls states are sent back from the browser to the server, but the server doesn’t know how to create the controls that’s why we had to do it every time the page is submitted. After the control has been created the Asp.Net framework is able to get it’s state from the page based on it’s name.

Ok, enough theory. Let’s give our controls and ID manually. Since the controls are added dynamically the ID’s have to be something that can be predicted. Let’s say: TextBox + a number. For this will change the createDynamicControls method to add a parameter which will be the number of the control added.


    //this method takes care of creating the controls
    private void createDynamicControls(int count)
    {
        TextBox tb = new TextBox();
        tb.TextChanged += TextBox_TextChanged;
        //now we set the control ID manually
        tb.ID = "TextBox" + count;
        PlaceHolder1.Controls.Add(tb);
        controlsList.Add(tb);
    }

When the add control button is clicked we need to pass the number to the method. We can use the control count that we’re storing in the ViewState.


    protected void Button1_Click(object sender, EventArgs e)
    {
        createDynamicControls((int)ViewState["count"]);
        //increment the number of controls
        ViewState["count"] = (int)ViewState["count"] + 1;
    }

Another place we need to change is the Page_Load event when the controls are re-created. Here for loop when we pass in the new parameter:


            for (int i = 0; i < controlCount; i++)
            {
                //notice that now we pass the i as parameter
                createDynamicControls(i);
            }

To test our new functionality we will add TextBox, a Button and a Label. We are going to inform the ID of the TextBox we want to get the value for. When the button is clicked the event will get the control and display it’s value in the label.


        <asp:TextBox ID="TextBoxControlId" runat="server"></asp:TextBox>
        <asp:button ID="ButtonGetValue" runat="server" text="Get value" 
            onclick="ButtonGetValue_Click" />
        Valor: <asp:Label ID="LabelValue" runat="server" Text=""></asp:Label>

And here is the event where we get the TextBox we want:


    protected void ButtonGetValue_Click(object sender, EventArgs e)
    {
        //find the control we want using the name informed by the user in the 
        //TextBoxControlId control
        TextBox tb = (TextBox)PlaceHolder1.FindControl(TextBoxControlId.Text);
        LabelValue.Text = tb.Text;
    }

Now if you add 3 TextBoxes (which will have id’s TextBox0, TextBox1 and TextBox2) and you input TextBox0 in the interface and hit the button the LabelValue control will show the value in the first TextBox.

This one was a bit longer than I would like to so I’ll try to make the next article shorter.

Here is the final version of our page after all of our modifications:


<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    System.Collections.Generic.List<TextBox> controlsList = new System.Collections.Generic.List<TextBox>();

    void Page_Load(object sender, EventArgs e)
    {
        //when the user first enters the page set the count as zero
        if (!IsPostBack)
        {
            ViewState["count"] = 0;
        }
        //on every subsequent postback, check the control count
        //and recreated all the controls
        else
        {
            int controlCount = (int)ViewState["count"];
            for (int i = 0; i < controlCount; i++)
            {
                //notice that now we pass the i as parameter
                createDynamicControls(i);
            }
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        createDynamicControls((int)ViewState["count"]);
        //increment the number of controls
        ViewState["count"] = (int)ViewState["count"] + 1;
    }

    //this method takes care of creating the controls
    private void createDynamicControls(int count)
    {
        TextBox tb = new TextBox();
        tb.TextChanged += TextBox_TextChanged;
        //now we set the control ID manually
        tb.ID = "TextBox" + count;
        PlaceHolder1.Controls.Add(tb);
        controlsList.Add(tb);
    }

    private void TextBox_TextChanged(object sender, EventArgs e)
    {
        //the sender is the control that fired the event
        //that is the control we want to change the color
        TextBox tb = (TextBox)sender;
        tb.BackColor = System.Drawing.Color.Yellow ;
    }

    protected void ButtonAdd_Click(object sender, EventArgs e)
    {
        int value = 0;
        foreach (TextBox tb in controlsList)
        {
            value += int.Parse(tb.Text);
        }
        LabelTotal.Text = value.ToString();
    }

    protected void ButtonGetValue_Click(object sender, EventArgs e)
    {
        //find the control we want using the name informed by the user in the 
        //TextBoxControlId control
        TextBox tb = (TextBox)PlaceHolder1.FindControl(TextBoxControlId.Text);
        LabelValue.Text = tb.Text;
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
        <br />
        <asp:Button ID="Button1" runat="server" Text="Add TextBox" 
            onclick="Button1_Click" />
        <br />
        <asp:Button ID="ButtonAdd" runat="server" Text="Add all values" 
            onclick="ButtonAdd_Click" />
        <br />
        Total:<asp:Label ID="LabelTotal" runat="server" Text=""></asp:Label>
        <br />
        <br />
        <asp:TextBox ID="TextBoxControlId" runat="server"></asp:TextBox>
        <asp:button ID="ButtonGetValue" runat="server" text="Get value" 
            onclick="ButtonGetValue_Click" />
        Value: <asp:Label ID="LabelValue" runat="server" Text=""></asp:Label>
    </div>
    </form>
</body>
</html>

See you next time.

0 comments | Filed Under: Tips and Tutorials | Tags: asp.net

Add Controls Dynamically - Part 3

Posted by gabriel, Mon Jul 21 21:55:00 UTC 2008

On the last article of this series we saw how we could assign event handlers to dynamically created controls and how the PlaceHolder control could help us add the controls in a more organized way.

Related posts:

In this article I want to show how you can keep a reference of a dynamically created control so that you can use it later somewhere else in your code. For this I’ll continue using the code created add the end of the last article of this series.

Now that you can add as many TextBoxes to the form as you want let’s say that you want to use them to input numeric values and then add up all the values for display. The first thing then is to decide where do we want to keep the reference to the controls. I chose to use a generic list of TextBox (List) but you could have chosen another structure that you feel more comfortable with.


System.Collections.Generic.List<TextBox> controlsList = new System.Collections.Generic.List<TextBox>();

Now that the list is declared and created the next step is deciding when we are going to add the controls to the list. To me using the method that adds the controls dynamically feels like the best choice, maybe someone has another idea (please share if you do). So the method would look like this:


    private void createDynamicControls()
    {
        TextBox tb = new TextBox();
        tb.TextChanged += TextBox_TextChanged;
        PlaceHolder1.Controls.Add(tb);
        controlsList.Add(tb);
    }

Easy, right? Ok, the last step now is adding a button to the form that will call the logic to add the values within all the controls and add a label that will display the result of the addition. The logic for adding the values is very simple, once you have a list with all the controls you only need to iterate through the list, get the value of the control and add it to a variable. Here is the code:


    protected void ButtonAdd_Click(object sender, EventArgs e)
    {
        int value = 0;
        foreach (TextBox tb in controlsList)
        {
            value += int.Parse(tb.Text);
        }
        LabelTotal.Text = value.ToString();
    }

Please notice that I have assumed that all the TextBoxes are provided with valid numeric values. We could improve the code to check for empty values and conversion errors however this is not the main goal of this article. Here is a complete version of the page after all our changes were made:


<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    System.Collections.Generic.List<TextBox> controlsList = new System.Collections.Generic.List<TextBox>();

    void Page_Load(object sender, EventArgs e)
    {
        //when the user first enters the page set the count as zero
        if (!IsPostBack)
        {
            ViewState["count"] = 0;
        }
        //on every subsequent postback, check the control count
        //and recreated all the controls
        else
        {
            int controlCount = (int)ViewState["count"];
            for (int i = 0; i < controlCount; i++)
            {
                createDynamicControls();
            }
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        createDynamicControls();
        //increment the number of controls
        ViewState["count"] = (int)ViewState["count"] + 1;        
    }

    //this method takes care of creating the controls

    private void createDynamicControls()
    {
        TextBox tb = new TextBox();
        tb.TextChanged += TextBox_TextChanged;
        PlaceHolder1.Controls.Add(tb);
        controlsList.Add(tb);
    }

    private void TextBox_TextChanged(object sender, EventArgs e)
    {
        //the sender is the control that fired the event
        //that is the control we want to change the color
        TextBox tb = (TextBox)sender;
        tb.BackColor = System.Drawing.Color.Yellow ;
    }

    protected void ButtonAdd_Click(object sender, EventArgs e)
    {
        int value = 0;
        foreach (TextBox tb in controlsList)
        {
            value += int.Parse(tb.Text);
        }
        LabelTotal.Text = value.ToString();
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
        <br />
        <asp:Button ID="Button1" runat="server" Text="Add TextBox" 
            onclick="Button1_Click" />
        <br />
        <asp:Button ID="ButtonAdd" runat="server" Text="Add all values" 
            onclick="ButtonAdd_Click" />
        <br />
        Total:<asp:Label ID="LabelTotal" runat="server" Text=""></asp:Label>
    </div>
    </form>
</body>
</html>

2 comments | Filed Under: Tips and Tutorials | Tags: asp.net

Add Controls Dynamically - Part 2

Posted by gabriel, Mon Jul 14 09:59:00 UTC 2008

This post continues what’s been done in the Part 1

On my last post I talked about creating controls dynamically in asp.net. In this post I’m going to continue with common issues or needs that users have based on what I noticed on the Asp.Net Forums

Related posts:

First I want to talk about assigning events to the controls that we are creating, this is a simple task but still and important topic.

Adding Events

The first thing we need to do is create a method that will be the handler for the event. When the event is fired on the control this is the method we want to be called to handle the event. In our example we are using TextBoxes so we want to handle the TextChanged event and make the background of the control yellow. Here is the method:


    private void TextBox_TextChanged(object sender, EventArgs e)
    {
        //the sender is the control that fired the event
        //that is the control we want to change the color
        TextBox tb = (TextBox)sender;
        tb.BackColor = System.Drawing.Color.Yellow ;
    }

The name of the method is irrelevant but it’s return type and parameters are not. If you create an event through VisualStudio you’ll notice that the signature of the method is the same.

Now that we have the method we need to set this method as the handler for the event on the controls that we are creating. Adding the method to the controls handler is as simples as this:


tb.TextChanged += TextBox_TextChanged;

If you add your controls now all of them will have this handler and it’s background will turn yellow (after submit) if you change the content of the textbox.

PlaceHolder

Up until now we’ve been adding the controls directly to the Form. This will cause the controls to be added to the end of the page after all other controls. This is fine as an example but might not be you desired result. We will you the PlaceHolder control as a container to our controls, this way we can put the PlaceHolder wherever we want in the page and the controls will be added within it.

Another advantage of the PlaceHolder control is that it doesn’t generate any html, it’s just the to serve (as it’s own name says) as a place holder. So you don’t need to worry about adding extra html just to have a place to put your controls in.

In our example I will put the PlaceHolder before the button that we are using just to show that the controls will no longer be added to the end of the page.

The new page with the events and the PlaceHolder control will be like this:


<script runat="server">

    void Page_Load(object sender, EventArgs e)
    {
        //when the user first enters the page set the count as zero
        if (!IsPostBack)
        {
            ViewState["count"] = 0;
        }
        //on every subsequent postback, check the control count
        //and recreated all the controls
        else
        {
            int controlCount = (int)ViewState["count"];
            for (int i = 0; i < controlCount; i++)
            {
                createDynamicControls();
            }
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        createDynamicControls();
        //increment the number of controls
        ViewState["count"] = (int)ViewState["count"] + 1;        
    }

    //this method takes care of creating the controls
    private void createDynamicControls()
    {
        TextBox tb = new TextBox();
        tb.TextChanged += TextBox_TextChanged;
        PlaceHolder1.Controls.Add(tb);
    }

    private void TextBox_TextChanged(object sender, EventArgs e)
    {
        //the sender is the control that fired the event
        //that is the control we want to change the color
        TextBox tb = (TextBox)sender;
        tb.BackColor = System.Drawing.Color.Yellow ;
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
        <asp:Button ID="Button1" runat="server" Text="Add TextBox" 
            onclick="Button1_Click" />
    </div>
    </form>
</body>
</html>

Stay tuned for more about dynamically created controls.

1 comment | Filed Under: Tips and Tutorials | Tags: asp.net

Add Controls Dynamically

Posted by gabriel, Sun Jul 06 18:35:00 UTC 2008

Dynamic controls are an interesting topic that keep showing up in the asp.net forums. I’ll try to explain the main points about creating and working with dynamically created controls in a few articles (this one would be too long otherwise).

First of all there are two points you need to understand:
  1. Adding the controls dynamically is easy, the tricky part is getting them to stick around.
  2. The controls are not kept between postbacks therefore you have to keep recreating them every time there is a postback.
  3. The best place to recreate the controls in the Page_Load or Page_Init events.

Creating a new control is easy, it’s just a matter of instantiate the class. Adding the control to the page is also easy you only need to add the new control to the page controls.


//create a new textbox
TextBox tb = new TextBox();
//add the new textbox to the page
Page.Form.Controls.Add(tb);

You’ve seen how easy it is to add the controls but if you don’t keep recreating them when you submit the page the dynamic controls will be gone.

First understand that this need to be recreated is not exclusive for dynamic created controls. Every time there is a postback the whole page is recreated. The difference is that all the controls that are declared in the aspx page are created automatically what gives the user the impression that the controls are always there (they are not!).

Since dynamically created controls are not hard coded anywhere (obviously) you are the one responsible for recreating them.

If you create a control in the Page_Load event you’ll notice that it works just like any control already in the aspx page:


<script runat="server">

    void Page_Load(object sender, EventArgs e)
    {
        TextBox tb = new TextBox();
        Page.Form.Controls.Add(tb);
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

    </div>
    </form>
</body>
</html>

Granted that if you could create the control like this you might declare it in the aspx page as well. Ok, so let’s improve our example and create a button that adds one and only one edit to the page. If the edit already exists the button won’t do any thing.


<script runat="server">

    void Page_Load(object sender, EventArgs e)
    {
        //means that the control has been created already so you 
        //need to recreate it
        if (ViewState["tb"] != null)
        {
            createDynamicControls();
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        //means the control has not been created yet
        //create the control and store the viewstate
        if (ViewState["tb"] == null)
        {
            createDynamicControls();
            ViewState["tb"] = true;
        }        
    }

    //this method takes care of creating the controls
    private void createDynamicControls()
    {
        TextBox tb = new TextBox();
        Page.Form.Controls.Add(tb);
    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Add TextBox" 
            onclick="Button1_Click" />
    </div>
    </form>
</body>
</html>

Notice that in this version of the code I created a method responsible for creating the dynamic control. This will help to encapsulate the method creation and avoid duplicating code. Also notice that I’m using the ViewState to help maintain a variable that indicates if the control has been added yet in order to avoid duplication.

When the user clicks the button I check my ViewState variable to see if the TextBox has been created, if it hasn’t I create the TextBox, add it to the page and set the ViewState variable. Now, as long as you don’t leave the page the control and it’s state will be maintained.

We could also let the user add an undefined number of TextBoxes to the page making some small changes.


<script runat="server">

    void Page_Load(object sender, EventArgs e)
    {
        //when the user first enters the page set the count as zero
        if (!IsPostBack)
        {
            ViewState["count"] = 0;
        }
        //on every subsequent postback, check the control count
        //and recreated all the controls
        else
        {
            int controlCount = (int)ViewState["count"];
            for (int i = 0; i < controlCount; i++)
            {
                createDynamicControls();
            }
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        createDynamicControls();
        //increment the number of controls
        ViewState["count"] = (int)ViewState["count"] + 1;        
    }

    //this method takes care of creating the controls
    private void createDynamicControls()
    {
        TextBox tb = new TextBox();
        Page.Form.Controls.Add(tb);
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Add TextBox" 
            onclick="Button1_Click" />
    </div>
    </form>
</body>
</html>
 

Now you are able to add any number of controls keeping the state of them all. On my next post I’ll keep working with dynamic created controls so stay tuned.

Related posts:

1 comment | Filed Under: Tips and Tutorials | Tags: asp.net

Bind DropDownList to Enum

Posted by gabriel, Tue Jul 01 22:12:00 UTC 2008

Unfortunately you can’t Databind an Enum to a DropDownList or to any control for that matter. You can however transform the Enum into something “bindable” like a HashTable.

First let’s define an Enum to use in our example:


public enum Cars
{
    Ford = 1,
    Kia = 2, 
    Mitsubishi = 3,
    Volkswagen = 4
}

Now let’s write a method that will read the enum and convert it into a HashTable.


    public Hashtable GetEnumForBind(Type enumeration)
    {
        //returns all the names in the enum
        string[] names = Enum.GetNames(enumeration);

        //return all the values in the enum
        Array values = Enum.GetValues(enumeration);

        Hashtable ht = new Hashtable();
        for (int i = 0; i < names.Length; i++)
        {
            //adds each item pair (value/name) to the Hash
            ht.Add(Convert.ToInt32(values.GetValue(i)).ToString(), names[i]);
        }
        return ht;
    }

Now that we have a method that will allow an enum to a HashTable all we need to do is bind the hash to the DropDownList.


        //call our previously defined method to create the HashTable
        Hashtable ht = GetEnumForBind(typeof(Cars));

        //set the HashTable as the DataSource
        DropDownList1.DataSource = ht;
        //set the value of the Hash as the display
        DropDownList1.DataTextField = "value";
        //set the key of the Hash as the value
        DropDownList1.DataValueField = "key";

        DropDownList1.DataBind();

That is it, it should now bind without problems. There are alternate solutions that do not involve binding but instead adding each item of the enum to the DropDownList. You can take a look at the asp.net forums to see alternate solutions proposed by other members.

0 comments | Filed Under: Tips and Tutorials | Tags: asp.net

Access Asp.Net WebService from PHP Client

Posted by gabriel, Tue Jun 17 12:28:00 UTC 2008

Creating and consuming webservices in asp.net is an easy task with the help of Visual Studio. Although most of the scenarios I worked with were always with asp.net applications consuming asp.net web services, which makes things even easier. This week however I learned something new when I had to get a PHP client application to connect to my asp.net webservices.

One of out clients was called saying that the service was not working. When I tested his PHP client I noticed the the parameters that he was passing where not getting to my webservice even though the service was being called. The only problem then was passing the parameters. I Googled a little and got my own PHP client running.

For the sake of this post let’s say that our webservice gets an string as a parameters and returns the same value, this will let us test our code. So here is the asp.net webservice:


[WebService(Namespace = "http://tempuri.org/")]
public class Service : System.Web.Services.WebService
{

    [WebMethod]
    public string MyTestMethod(string myParameter)
    {
        return "The value of the parameter is: " + myParameter;
    }

}

As you can see there’s nothing to it.

The PHP code is not much harder once you Google a little. First you have to have NuSoap Library which has the webservices infrastructure for PHP. You may put it in the same directory of your test page. Then you code a simple client to access our service:


<?php

    require_once('./nusoap.inc');

    $wsdl = "http://mysite/myapp/Service.asmx?wsdl";

    $mynamespace = "http://tempuri.org/";

    $theVariable = array('myParameter'=> 'gabriel');

    $s = new SoapClient($wsdl,true);

    $result = $s->call('MyTestMethod',$theVariable);

    echo "<h1>Resultado:</h1>";

    echo "<pre>"; print_r($result); print "</pre>";
?>

After I had the code I could verify for my self that my client was right. The parameters in the above code are not getting to the webservice. The coding is right, I checked in several sites in the Internet, so where could the problem be?

Well, SOAP specification allows for two formatting options: Style and Use. Style handles the formatting of the Body element of the envelope. Style allows for 2 values:
  1. RPC (Remote Procedure Call) which is the older format;
  2. Document which is a newer format and is VisualStudio default format.

By now I bet you have figured out the solution, right? If you said that PHP default encoding is RPC and asp.net default encoding is Document then you’re right on.

How to solve the problem? Well, you can solve the problem on both ends, it all depends on your choice. First let’s fix it on the asp.net side, it’s really simple. All you have to do is use the SoapRpcMethod attribute on WebMethod, like this:


[WebService(Namespace = "http://tempuri.org/")]
public class Service : System.Web.Services.WebService
{

    [SoapRpcMethod()]
    [WebMethod]
    public string MyTestMethod(string myParameter)
    {
        return "The value of the parameter is: " + myParameter;
    }

}

That’s it, the PHP client starts to work instantly.

This is a good solution if you only had PHP clients, since that was not my case I didn’t want to mess with my webservice and have to make changes to all other asp.net clients. I wanted to solve the problem on the PHP client, so let’s see how we could code the PHP client to fix the problem.

<?php

    require_once('./nusoap.inc');

    $wsdl = "http://mysite/myapp/Service.asmx?wsdl";

    $mynamespace = "http://tempuri.org/";

    $theVariable = array('myParameter'=> 'gabriel');

    $s = new SoapClient($wsdl,true);

    //here is the only change you need to do
    $result = $s->call('MyTestMethod',array('parameters' =>  $theVariable));

    echo "<h1>Resultado:</h1>";

    echo "<pre>"; print_r($result); print "</pre>";
?>

What I had to do in the PHP code was to add an extra array around the array with the original variables. This handles the difference in the Document encoding used by asp.net.

This problem really got on my nerves last week and I’m really glad to have found a solution. As usual I wanted to share this with the world and maybe avoid the same headache to others. Ohh, and I also got to learn a little php on the way…

Happy coding friends!

1 comment | Filed Under: Tips and Tutorials | Tags: asp.net