Archive for the ‘WCF’ Category

Okay, I’ve not blogged for a while and this was mainly due to being subjected to SharePoint 2007 development once again.  However, I’m now into the land of SharePoint 2013 and I’ve no doubt I will be actively posting once more as I discover various nuances of the new environment.

So, here’s my first, which was a bit of a head scratcher!! After creating a custom list, I tried to add a new list item and received the following unhelpful error.

clip_image002

After a bit of Google-ing as few fixes were suggested, but none of which seemed like a viable solution. For reference, so you don’t go down same route, these were :

  • Enable Anonymous access
  • Restart the SharePoint Search Host Controller  service
  • Lack of RAM

None of these work, so don’t even try.

Next step, was to go to the logs where I found a call was being made to the /_vti_bin/client.svc/ProcessQuery

However, on opening the WCF service in the browser I received the following 500 error  “Operation is not valid due to the current state of the object” which lead me the eventual problem.

My web.config didn’t have a serviceHostingEnvironment element.  Adding the following to the <system.serviceModel> section resolved the issue

Service Hosting Element
  1. <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

However, you may have the following already in your config

Wrong Service Hosting Environ
  1.  
  2. <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>

If you remove  multipleSiteBindingsEnabled="true"  it should work

Hope this helps you save a few hours

Open-mouthed smile

Advertisements

AJAX Accordion OutOfMemoryException

Posted: 29th March 2010 in AJAX, JQuery, WCF

Recently I came across a problem with the ASP.NET AJAX accordion control which caused my machine to have a System.OutOfMemoryException. This was caused by an attempt to bind a large result set returned from a WCF service  to the accordion control. The error never directly specified out of memory, but instead display the following webpage error: “Could not get the value property. Not enough storage is available to complete this operation”

image

This is actually a SOAP error, but its effectively the same thing. There is simply too much data for the machine to cope.

After some investigation I found that this problem was down to the fact that the accordion control not only loads the header detail for the bound list, but all the content detail too. In my case, the content control contained a lot of dropdown lists.  Firstly, I thought about implementing paging, but after consultation with the client I soon discovered that this was not an option.

So, to allow me to load the full list I had to change how the master and detail worked. Here’s how I went about it.

Firstly, I created a user control for the detail to be displayed and instead of loading the control in the html of the accordion content template I added a place holder as shown in Figure 1.

Figure 1
  1. <ContentTemplate>
  2. <asp:PlaceHolde

Now, I have to load this control dynamically. However, I only want to load it for the first item of the accordion. To do this I used the OnItemDataBound event of the accordion as can be seen below in Figure 2.

Figure 2
  1. protected void CircuitAccordion_ItemDataBound(object sender, AccordionItemEventArgs e)
  2. {
  3. if (e.ItemType != AccordionItemType.Content || ((Accordion) sender).Panes.Count > 1)
  4. {
  5. return;
  6. }
  7. var circuitDto = e.Item as CircuitDto;
  8. if (circuitDto == null)
  9. {
  10. return;
  11. }
  12. var circuitDetail = (CircuitDetail)LoadControl(“UserControls/CircuitDetail.ascx”);
  13. circuitDetail.Circuit = circuitDto;
  14. var circuitUserControlPlaceHolder =
  15. e.AccordionItem.FindControl(“circuitUserControlPlaceHolder”) as PlaceHolder;
  16. if (circuitUserControlPlaceHolder == null)
  17. {
  18. return;
  19. }
  20. circuitUserControlPlaceHolder.Controls.Add(circuitDetail);
  21. }

Great, now the first item loads, but not the rest.  To get the other items to load I needed to use a little jquery and a AJAX enabled WCF service (to get the data for each item).

To override the functionality of the accordion control I first need to create a client side event handler for  the on selected index changed event. This can be seen in figure 3 and attach the handler on the page load figure 4

Figure 3
  1. // handles the event which fires on the accordion selected index changing
  2. function onAccordionSelectedIndexChanged(sender, eventArgs) {
  3. var contentTemplate = $(‘#’ + sender._id.replace(‘_AccordionExtender’, ‘_Pane_’ + sender.get_SelectedIndex() + ‘_content’));
  4. contentTemplate.append($(“fieldset[id*=’DetailsControl’]:visible”));
  5. var headerTemplate = sender._id.replace(‘_AccordionExtender’, ‘_Pane_’ + sender.get_SelectedIndex() + ‘_header’);
  6. var id = $(‘#’ + headerTemplate + ‘_idHiddenTextBox’).val();
  7. var tabContainer = $get(‘<%=locationTabContainer.ClientID%>’).control;
  8. loadDetailControlData(tabContainer.get_activeTab().get_headerText(), id);
  9. }

In figure 3 I perform the following steps:

  • Line 3 – I get reference to the content template of the header which has been clicked.
  • Line 4 – I append the visible details user control to the associated content template of the selected index of the header template clicked.
  • Line 5 – Get reference to the header template to allow access to the hidden textbox control.
  • Line 6 – Retreive the value of the primary key, which is in a hidden textbox control named idHiddenTextbox in the header template pane.
  • Line 7- Get reference to the selected tab
  • Line 8 –  Pass the id and the selected tab control to the loadDetailControlData function in figure 5

To add the event handler to the control I use the javascript pageLoad() function as can be seen in figure 4.

Figure 4
  1. function pageLoad() {
  2. $find(‘<%= devicesAccordion.ClientID %>’ + ‘_AccordionExtender’).add_selectedIndexChanged(onAccordionSelectedIndexChanged);
  3. $find(‘<%= cabinetsAccordion.ClientID %>’ + ‘_AccordionExtender’).add_selectedIndexChanged(onAccordionSelectedIndexChanged);
  4. $find(‘<%= endBCircuitsAccordion.ClientID %>’ + ‘_AccordionExtender’).add_selectedIndexChanged(onAccordionSelectedIndexChanged);
  5. $find(‘<%= endACircuitsAccordion.ClientID %>’ + ‘_AccordionExtender’).add_selectedIndexChanged(onAccordionSelectedIndexChanged);
  6. $find(‘<%= nonNetworkDevicesAccordion.ClientID %>’ + ‘_AccordionExtender’).add_selectedIndexChanged(onAccordionSelectedIndexChanged);
  7. }

In this particular situation, I have a tab control which, in turn, contains the accordion controls. So, I created a JavaScript function to load the detail control data dependent on the selected tab, seen in figure 5 which call the WCF service shown in figure 6 and ultimately set the field values from the service response seen in figure 7.

figure 5
  1. function loadDetailControlData(tabHeaderText, id) {
  2. switch (tabHeaderText) {
  3. case ‘Cabinets’:
  4. getCabinet(id);
  5. break;
  6. case ‘Devices’:
  7. getDevice(id);
  8. break;
  9. case ‘End A Circuits’:
  10. case ‘End B Circuits’:
  11. getCircuit(id);
  12. break;
  13. case ‘Non-Network Devices’:
  14. getNonNetworkDevice(id);
  15. break;
  16. }
  17. }

Figure 6 shows the call to the WCF service using jquery. This function is called from the function above in Figure 5.

Figure 6
  1. function getCircuit(circuitId) {
  2. $.ajax({
  3. url: http://localhost:10785/LocationServiceAjax.svc/GetCircuit&#8221;,
  4. type: “POST”,
  5. contentType: “application/json”,
  6. data: ‘{“circuitId”:’ + circuitId + ‘}’,
  7. dataType: “json”,
  8. success: function(data) {
  9. setCircuitDetail(data.d);
  10. }
  11. });
  12. }

Seen below is the call-back function to set the control values of the details form which are returned from the WCF Ajax response seen in figure 6

Figure 7
  1. // Sets the circuit detail form callback from the ajax wcf call.
  2. function setCircuitDetail(circuit) {
  3. if (circuit == null) { alert(“Something is not configure correctly.”); return; }
  4. $(“input[id$=’circuitReferenceTextBox’]:visible”).val(circuit.CircuitReference);
  5. $(“select[id$=’circuitUsageDropDownList’]:visible”).val(circuit.Usage.Description);
  6. $(“select[id$=’circuitTypeDropDownList’]:visible”).val(circuit.Type.Name);
  7. $(“select[id$=’circuitOwnerDropDownList’]:visible”).val(circuit.Owner.Name);
  8. $(“select[id$=’circuitStatusDropDownList’]:visible”).val(circuit.Status.Status);
  9. $(“select[id$=’endACircuitLocationDropDownList’]:visible”).val(circuit.EndALocationCode);
  10. $(“select[id$=’endBCircuitLocationDropDownList’]:visible”).val(circuit.EndBLocationCode);
  11. }

Hopefully this post helps someone as it took me a while to work it out… 🙂

WCF Client Generic Base Class

Posted: 26th February 2010 in WCF

Further to my previous blog entry about the WCF 10 connection limit and its inability to implement the IDisposable interface or allow the use of the “using block” to free up the connections, I decided to write a generic base class.

This base class does not close the connection automatically,nor does it dispose of the connection, but it does allow me to create and use a service client a lot easier.

  1. public class BaseServiceConnector<T> where T : ICommunicationObject, new()
  2. {
  3. private T serviceClient = new T();
  4. /// <summary>
  5. /// Instance variable to access the Cache from the enterprise library
  6. /// </summary>
  7. private static readonly ICacheManager cacheManager = CacheFactory.GetCacheManager();
  8. /// <summary>
  9. /// Gets the service client.
  10. /// </summary>
  11. /// <value>The service client.</value>
  12. protected T ServiceClient
  13. {
  14. get
  15. {
  16. try
  17. {
  18. if (this.serviceClient.Equals(default(T)) || this.serviceClient.State == CommunicationState.Closed)
  19. {
  20. this.serviceClient = new T();
  21. }
  22. this.ReEstablishProxyIfNecessary();
  23. }
  24. catch (FaultException)
  25. {
  26. this.ReEstablishProxyIfNecessary();
  27. }
  28. catch (Exception)
  29. {
  30. this.ReEstablishProxyIfNecessary();
  31. }
  32. return this.serviceClient;
  33. }
  34. }
  35. /// <summary>
  36. /// Instance variable to access the Cache from the enterprise library
  37. /// </summary>
  38. public ICacheManager CacheManager
  39. {
  40. get { return cacheManager; }
  41. }
  42. /// <summary>
  43. /// Re-establish proxy if necessary.
  44. /// </summary>
  45. private void ReEstablishProxyIfNecessary()
  46. {
  47. if (this.serviceClient.State != CommunicationState.Faulted)
  48. {
  49. return;
  50. }
  51. this.serviceClient.Abort();
  52. this.serviceClient = new T();
  53. }
  54. }

Now I can create service  clients and reuse the code all I have to do is inherit from it and pass in the proxy client instance name.

  1. public class LookupServiceCache : BaseServiceConnector<LookupServiceClient>, ILookupServiceCache
  2. {
  3. #region Lookups
  4. /// <summary>
  5. /// Gets the towns.
  6. /// </summary>
  7. /// <returns>The list from the cache if it exists; or from the database</returns>
  8. public IList<TownDto> GetTowns()
  9. {
  10. var cacheKey = LookupDataType.Towns.ToString();
  11. if (!this.CacheManager.Contains(cacheKey))
  12. {
  13. var towns = this.ServiceClient.GetTowns();
  14. this.CacheManager.Add(
  15. cacheKey,
  16. towns,
  17. CacheItemPriority.Normal,
  18. null,
  19. new SlidingTime(TimeSpan.FromMinutes(Constants.CacheTimeout)));
  20. this.ServiceClient.Close();
  21. }
  22. return (IList<TownDto>)this.CacheManager.GetData(cacheKey);
  23. }
  24. }

I’ve found this useful for creating a business logic layer above the service for purpose of caching, validation, etc.

Given the task of populating and binding controls within an AJAX accordion control I thought things would be easy.  However, binding to a selected index of a dropdown control was not as easy as I first suspected.

Below is one of the accordion section included in my tab container.

Accordion with dropdown
  1. <asp:Accordion ID="devicesAccordion" runat="server" OnItemDataBound="DeviceAccordion_ItemDataBound">
  2.                                 <HeaderTemplate>
  3.                                      <tr>
  4.                                         <td><asp:Label ID="Label2" Text='<%# Eval("Name") %>' runat="server"  /></td>
  5.                                      </tr>
  6.                                 </HeaderTemplate>
  7.                                 <ContentTemplate>
  8.                                     <label for="nameTextBox">Name</label>
  9.                                     <asp:TextBox ID="nameTextBox" Text='<%# Eval("Name") %>' runat="server" />
  10.                                     <label for="deviceStatusDropDownList">Status</label>
  11.                                     <asp:DropDownList ID="deviceStatusDropDownList" runat="server" />
  12.                                     <asp:Button runat="server" ID="updateDevicesButton" CommandName="UpdateDevice" OnCommand="UpdateDevicesButton_Command" CommandArgument='<%# Eval("Id") %>' Text="Update" />
  13.                                 </ContentTemplate>
  14.                             </asp:Accordion>

Next, I had to bind the value from the DB to the status of the device and to do this I use the item data bound event of the accordion control. Firstly, I have to AccordionItemEvent being passed in is within the content part of the  control, i.e. the one being edited.

Once I’ve confirmed this, I need to convert the item in the control to the Data Transfer Object being retrieved from the WCF Service.  Then, if the cast to the DTO is not null. I find the control and set the value of the dropdown.

Binding an accordion item
  1. /// <summary>
  2.         /// Event handler when a new item is bound in the contentTemplate of the devices accordion.
  3.         /// </summary>
  4.         /// <param name="sender">The sender.</param>
  5.         /// <param name="e">The <see cref="AjaxControlToolkit.AccordionItemEventArgs"/> instance containing the event data.</param>
  6.         protected void DeviceAccordion_ItemDataBound(object sender, AccordionItemEventArgs e)
  7.         {
  8.             if (e.ItemType != AccordionItemType.Content)
  9.             {
  10.                 return;
  11.             }
  12.  
  13.             var deviceDto = e.Item as DeviceDto;
  14.             if (deviceDto == null)
  15.             {
  16.                 return;
  17.             }
  18.  
  19.             var dropDownList = e.AccordionItem.FindControl("deviceStatusDropDownList") as DropDownList;
  20.             if (dropDownList == null)
  21.             {
  22.                 return;
  23.             }
  24.  
  25.             this.PopulateDropDownListAndSetValue(dropDownList, LookupDataType.DeviceStatuses, deviceDto.Status.Status);
  26.         }

To help me with this process, I created a basic interface to be implemented by all DTO’s that can be used in a dropdown. 

Interface for Dropdowns
  1. /// <summary>
  2.     /// Interface to be implemeted to use a class as part of a drop down list.
  3.     /// </summary>
  4.     public interface ILookupData
  5.     {
  6.         /// <summary>
  7.         /// Gets the key for the lookup data.
  8.         /// </summary>
  9.         /// <value>The key of the lookup.</value>
  10.         string Key { get; }
  11.  
  12.         /// <summary>
  13.         /// Gets the value for the lookup data.
  14.         /// </summary>
  15.         /// <value>The value of the lookup.</value>
  16.         string Value { get; }
  17.     }

I also created a method to populate and set the value of the dropdown’s  selected index setting the Text and Key properties defined in the above interface.

Populate and set the dropdown
  1. /// <summary>
  2.         /// Populates the drop down list and set value.
  3.         /// </summary>
  4.         /// <param name="dropDownList">The drop down list.</param>
  5.         /// <param name="lookupDataType">Type of the lookup data.</param>
  6.         /// <param name="selectedValue">The selected value.</param>
  7.         protected void PopulateDropDownListAndSetValue(ListControl dropDownList, LookupDataType lookupDataType, string selectedValue)
  8.         {
  9.             dropDownList.DataSource = this.serviceConnector.GetLookupData(lookupDataType);
  10.             dropDownList.DataTextField = "Value";
  11.             dropDownList.DataValueField = "Key";
  12.             dropDownList.DataBind();
  13.             if (string.IsNullOrEmpty(selectedValue))
  14.             {
  15.                 return;
  16.             }
  17.  
  18.             dropDownList.SelectedValue = selectedValue;
  19.         }

In the code sample above it is shown that the data source for the the dropdown comes from a WCF Service which, in turn, returns a list of interfaces ILookupData. The working and casting for this service call is shown in the code sample below.

Casting items in a list
  1. /// <summary>
  2.         /// Gets the lookup data.
  3.         /// </summary>
  4.         /// <param name="lookupDataType">Type of the lookup data.</param>
  5.         /// <returns></returns>
  6.         public IList<LookupData> GetLookupData(LookupDataType lookupDataType)
  7.         {
  8.             IList<ILookupData> lookDataList = new List<ILookupData>();
  9.             switch (lookupDataType)
  10.             {
  11.                 case LookupDataType.Countries:
  12.                     lookDataList = this.GetCountries().ToList().ConvertAll(item => (ILookupData)item);
  13.                     break;
  14.                 case LookupDataType.DeviceStatuses:
  15.                     lookDataList = this.GetDevicesStatuses().ToList().ConvertAll(item => (ILookupData)item);
  16.                     break;
  17.                 case LookupDataType.Towns:
  18.                     lookDataList = this.GetAllTowns().ToList().ConvertAll(item => (ILookupData)item);
  19.                     break;
  20.             }
  21.  
  22.             return lookDataList.ToList().ConvertAll(item => (LookupData)item);
  23.         }

Hopefully, this post helps someone out there…

WCF 10 connection limitation

Posted: 15th February 2010 in AJAX, WCF

Recently, I had a problem with an AJAX enabled application which was calling a WCF service. As can be seen below, in my calls to the Service, I used the “using statement” to allow the connection to the service to be closed after use. 

Code Snippet
  1. /// <summary>
  2.         /// Gets the towns.
  3.         /// </summary>
  4.         /// <returns>The list from the cache if it exists; or from the database</returns>
  5.         public List<TownDto> GetTowns()
  6.         {
  7.             if (!this.cacheManager.Contains("towns"))
  8.             {
  9.                 using (var svc = new NetworkServiceClient())
  10.                 {
  11.                     var towns = svc.GetAllTowns();
  12.                     this.cacheManager.Add(
  13.                         "towns",
  14.                         towns,
  15.                         CacheItemPriority.Normal,
  16.                         null,
  17.                         new SlidingTime(TimeSpan.FromMinutes(Constants.CacheTimeout)));
  18.                 }
  19.             }
  20.  
  21.             return (List<TownDto>)this.cacheManager.GetData("towns");
  22.         }

However, as i played with the application it became apparent that the more calls its made the slower the application became.   Eventually, after wading threw all the application tiers I found the culprit was: by default WCF only allows 10 connections, which meant my connections weren’t being closed by the using statement.

The code has now been refactored to close the service client explicitly. It now works!

Returning Generic List from a WCF service

Posted: 13th January 2010 in WCF

By default a WCF or ASMX service returns list as arrays. However, this can be overcome by amending the properties of the service proxy.

Right click on the service reference and choose configure service reference and you should be presented with a screen similar to the one below.
Configuring a service to return a generic list

Choose System.Collections.Generic.List from the drop down.

Listed below are some issues and solution you may come across when trying access a LINQ to Entity layer from a WCF Service located in a separate project.

Problem:
Argument Exception: “The specified named connection is either not found in the configuration, not intended to be used with the EntityClient Provider, not valid.”

Argument Exception: The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid

Solution:

The class library which contains the EDMX file contains an app.config file with the entity connection string. When access this from the WCF layer, there is no reference to it unless you include it in the web.config of the WCF layer

To fix the problem, copy the connection string from the app.config to the ConnectionStrings section of the web.config of the WCF project.

However, on doing this, you may receive another exception message:

MetadataException: Unable to load the specified metadata resource.
MetadataException : Unable to load the specified metadata resource

connectionString=”metadata=res://*/Model.Project.csdl|res://*/Model.Project.ssdl|res://*/Model.Project.msl;

to

connectionString=”metadata=res://*/;