Thursday, November 22, 2012

Change the object graph or increase the MaxItemsInObjectGraph quota


We are suing WCF RIA services for our Silverlight application  for data Access.Suddenly We got an error for some of the Service requests as "Request Aborted"  in Firebug.

After adding below diagnostics code to my web.config file,I ran the application one more time.


<system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="traceListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "c:\Traces.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
When I opened the Svclog file, I came to know the exact cause of this Request aborted Exception. Below is the Exception details,
There was an error while trying to serialize parameter http://tempuri.org/:GetOrdersResult. The InnerException message was 'Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota. '.  Please see InnerException for more details.
I googled for this Exception and all are saying that I need to restrict the results to a specific number and I can achieve this by pagination. I understood that, this the feasible solution , but it costs me an extra effort of some more billing hours and our client is not willing to do so.
When I closely observed my config settings as shown below,

<system.serviceModel>
    <services>
      <service behaviorConfiguration="MyApp.Web.Services.MyAppDomainService" name="MyApp.Web.Services.MyAppDomainService"></service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyApp.Web.Services.MyAppDomainService">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceThrottling maxConcurrentSessions="2147483647" maxConcurrentInstances="2147483647" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <!--To Use Session variables in the Services-->
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
I have set it to the max length of an Integer value that is 2147483647,but in the Exception details It is saying that the value is set to 65536. After a lot of R and D , I came to know from Stack Exchange forums that when we are using more than one Web service, in our project, then we should remove Service specific settings from the web.config file.





Monday, October 22, 2012

Multi Select Listbox "Select All" should select all items in the Listbox.



We got a requirement from our client that, when user clicks on the “All” option from a Silverlight list box, and then all Items from that Listbox should be selected.

Here below are the three scenarios.

·         User Clicks on “All” option to select All Items, then all items in the list to be selected.
·         User can select all items individually using Ctl key, then the option “All” also to be selected, even the user not selects it.

·         If any of the Items got unselected, then “All” option also to be unselected.

Here we are trying to write the logic in List Box Selection Changed event, there is a possibility that we may end in infinite loop, if we are trying to implement it without taking care. As selection and de selection will raise Selection Changed event, we should do something to avoid it.

Even if Selection Changed event logic is having some code to be executed, when user really changes selection, that code will be executed unnecessarily because of our newly added code. So it will create latency and performance will be down.

After some research, I have come up with below solution.

        void LstGeographics_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBox lstBox = sender as ListBox;
            if (lstBox.Tag != null && (bool)lstBox.Tag == false)
            {
                lstBox.Tag = true;
                return;
            }
            SetRegionListBoxSelection((ListBox)sender, e);
      
              DoSomething();
        }


In the above event handler, we are checking for ListBox’s tag property, which we are setting to false, when our code itself changing the selection, without user interaction.
So if it is false, then we can avoid unnecessary execution of the method “Dosomething”


   public void SetRegionListBoxSelection(ListBox lstBox, SelectionChangedEventArgs e)
        {
            try
            {
                if (e.AddedItems.Count == 0 && e.RemovedItems.Count == 0)
                    return;
                if (lstBox.SelectedItems.Count == lstBox.Items.Count - 1)
                {
                    if (!e.AddedItems.Cast<ClassName>().Contains(lstBox.Items.Cast<ClassName>().First()))
                        if (!e.RemovedItems.Cast<ClassName>().Contains(lstBox.Items.Cast<ClassName>().First()))
                        {
                            lstBox.Tag = false;
                            lstBox.SelectAll();
                            return;
                        }
                        else
                        {
                            lstBox.Tag = false;
                            lstBox.SelectedItems.Clear();
                        }
                }

                if (e.AddedItems.Cast<ClassName>().Contains(lstBox.Items.Cast<ClassName>().First()))
                {
                    lstBox.Tag = false;
                    lstBox.SelectAll();
                    return;
                }

                if (lstBox.SelectedItems.Count <= lstBox.Items.Count - 1)
                {
                    lstBox.Tag = false;
                    lstBox.SelectedItems.Remove(lstBox.Items.Cast<ClassName>().First());
                   
                }

            }
            catch (Exception ex)
            {
            }
            lstBox.Tag = true;
        }