Recently I ran into a problem where I needed to reduce the size of a page, we had a page with a lot of drop down controls that may or my not be used. The problem with this was the size of the html was huge, every one of the controls was fully populated with over 50 items, next the view state was equally huge storing all of that content. The Solution, using WCF to load the control’s content on demand.
Starting off we need to get WCF configured, and this confused me, I had to manually register WCF in IIS, WHAT!! ok to save you the hassle of having to research how to do this, execute c:\WINDOWS\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe –i and your good to go.
We have two options for populating the dropdowns, you can use a 3rd party control like Telerik’s radcombobox, or roll your own, which in some ways is fairly simple but rather involved, for right now I’m going to show you how to roll your own, to see how to use radComboBox see here.
Lets start with the WCF service, create a Ajax enabled WCF service. For what ever reason I had to remove the namespace to get this to work, and the examples I found online had it removed as well, this is something I’m going to research more on later. Next we need to build a data entity to hold the data, nothing fancy just something like this
1: public class Item
2: {
3: public string Text { get; set; }
4: public string Value { get; set;}
5: }
6:
7: public class Items : Collection<Item>
8: {}
1: [ServiceContract(Namespace = "")]
2: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
3: public class DataService
4: {
5: [OperationContract]
6: public Items GetData()
7: {
8: Items myItems = new Items();
9: for (int i = 0; i < 5; i++)
10: {
11: Item newItem = new Item()
12: {
13: Text = string.Format("value {0}", i),
14: Value = i.ToString()
15: };
16: myItems.Add(newItem);
17: }
18: return myItems;
19: }
20: }
1: <system.serviceModel>
2: <behaviors>
3: <endpointBehaviors>
4: <behavior name="DataServiceAspNetAjaxBehavior">
5: <enableWebScript />
6: </behavior>
7: </endpointBehaviors>
8: </behaviors>
9: <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
10: <services>
11: <service name="DataService">
12: <endpoint address="" behaviorConfiguration="DataServiceAspNetAjaxBehavior"
13: binding="webHttpBinding" contract="DataService" />
14: </service>
15: </services>
16: </system.serviceModel>
Next we add the service reference to the page using the script manager tag
1: <asp:ScriptManager ID="scriptManager" runat="server">
2: <Services>
3: <asp:ServiceReference Path="/DataService.svc" />
4: </Services>
5: </asp:ScriptManager>
1: <select
2: id="dropDownList"
3: runat="server"
4: enableviewstate="false"
5: style="width:200px;"
6: onfocus="populateDropDown(this);">
7: </select>
1: var Control;
2: function populateDropDown(dropdown) {
3: Control = dropdown;
4: DataService.GetData(dropDownRequest_onSuccess, onFailure);
5: }
1: var selectedOptionValue;
2:
3: function dropDownRequest_onSuccess(result) {
4: Control.options.length = 0;
5: for (var x = 0; x < result.length; x++) {
6: var opt = document.createElement("option");
7: opt.text = result[x].Text;
8: opt.value = result[x].Value;
9: if (result[x].Value == selectedOptionValue) {
10: opt.setAttribute("selected", "true");
11: }
12: Control.options.add(opt);
13: }
14: }
15:
16: function onFailure(result) {
17: window.alert(result);
18: }
The onFailure is called when the service call fails, and for this we are just doing a simple alert to say it failed.
The next part is getting the data out when the page is submitted, because we are not using any view state we can’t get the value the same way we would with a regular asp.net control, we have to pull it from Request.Form collection.
1: string value = Request.Form[dropDownList.ID];
1: private void setValue()
2: {
3: string script = string.Format("setpopulateDropdown('{0}',{1});", dropDownList.ClientID, Request.Form[dropDownList.ID]);
4: ClientScript.RegisterStartupScript(typeof(Page),"setDropdownValue",script,true);
5:
6: }
to call this javascript function
1: function setpopulateDropdown(controlId, value) {
2: Control = document.getElementById(controlId);
3: selectedOptionValue = value;
4: populateDropDown(Control);
5: }
This sets the control to be updated, set the selected value, then populates the the control from the webservice.
Like I said it’s kind of a long process but you can cut down your page size a lot if your doing multiple dropdowns with large amounts of data that may not be used.
As always the full source code for this project is available (here).