Showing posts with label Configuration. Show all posts
Showing posts with label Configuration. Show all posts

Friday, 29 October 2010

Web.config settings - e.g. ViewState, Session

A common issue raised in the CRM Development forum is of custom web pages that work correctly in a development environment, but then fail to work when deployed into the CRM web site. The most common reason for this is that the CRM web.config overrides some of the default ASP.Net configuration settings.

The relevant entries in the CRM web.config (in the root of the CRM web site) are:

<pages buffer="true" enableSessionState="false" enableViewState="false" validateRequest="false/">
<sessionState mode="Off"/>

These have 2 main consequences:
  1. Session State is disabled. This issue is relatively easy to diagnose, as you tend to get a clear error message if trying to use session state when it is disabled
  2. ViewState is disabled. This can be a more subtle effect, as developers often rely on viewState without necessarily being aware of it. ViewState is what allows ASP.Net web controls to maintain property values across web requests; if it is disabled then it leads to symptoms such as values not being retained, or list boxes losing their contents

The solution for viewState is straightforward. You can reenable viewState for you application either in the web.config in your application directory, or at the page level within the <@Page> directive. These looks like the following:

web.config:
<pages enableViewState="true" />

Page directive:
<@Page EnableViewState="true" />

Session state is a bit more complex, as this is configured at the web application level. Personally, I've never seen any reason to use session state within custom code in the CRM web site; CRM doesn't use this, and I find it best to mimic CRM behaviour wherever possible.

And one final point about best practise; as this post demonstrates, it is best not to rely on the default ASP .Net configuration settings, rather I find it best to always explicitly enable or disable settings in the local web.config

Thursday, 4 September 2008

SQL Timeouts in CRM - Generic SQL Error

I often find myself answering forum posts about SQL errors (the most common error is 'Generic SQL Error'). By far the most likely cause of this error is a timeout when accessing SQL server. If this is a case your options are to increase the timeout, or to try and ensure the query does not take so long.

Increase the Timeout
The SQL timeout is controlled by a registry value on each CRM server:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM\OLEDBTimeout

This value does not exist by default, and if it does not exist then the default value will be 30 seconds. To change it, add the registry value (of type DWORD), and put in the value you want (measured in seconds). Then you have to recycle the CrmAppPool application pool for the change to take effect (this is a step most Microsoft documentation omits to mention); do this we IISReset, or less drastically via iisapp.vbs

Reduce the time taken by the query
This may not be so simple, as you may have little control over the query. If the query is run as a result of your code (e.g. through a RetrieveMultiple request), then you may be able to make useful changes. For example, RetrieveMultiple requests on activities are not necessarily processed very efficiently by CRM (the problem is the way that is accesses the activity parties), and I've been able to make significant improvements by using a FetchXml query instead, which gives closer control over the joins used.

Otherwise, the other query optimisation option is to add indexes in SQL Server. This is a massive topic in its own right (I used to deliver 5 day training courses just on this topic), so I'm not going to go into detail here. The general steps are:
  1. Identify the SQL query that takes the time - I use CRM tracing for this - http://support.microsoft.com/kb/907490
  2. Use the SQL Management Studio and SQL Profiler to identify the query execution plan and to get recommendations about possible indexes

There are 2 important things to take into account:

  1. Although adding an index may improve the performance of one query, it can adversely affect other SQL operations - most obviously data updates. There is no easy solution to this, though the SQL Profiler can help you if you capture and analyse a representative sample of SQL operations
  2. Some out-dated CRM documentation suggested that it is unsupported to add indexes to the MSCRM database. However, adding indexes is supported, providing the index does not implement any constraints (i.e. it's not a UNIQUE index)

Friday, 23 November 2007

External access from a Virtual Environment

We do almost all our CRM development and testing within virtual images. This confers many benefits, but raises issues if you need connect the image to the outside world. One example is when registering software; another is when developing callouts / plugins that communicate with external web services.

The major issue arises with a self-contained image that is a domain controller in its own domain, as well as a SQL server and CRM server. Active Directory depends on DNS, so the image has to be its own DNS server, which forces it to have a fixed IP address, which we place on separate IP private IP subnet (e.g. 192.168.x.0). This essentially prevents this IP address and adapter being used externally. With just the one adapter and IP address, you can’t change the IP address to a dynamic one (e.g. from DHCP), because within the image that breaks DNS, which breaks AD, which breaks CRM.

So, the solution; add a separate network adapter to the image, using an external IP address. With Microsoft Virtual PC or Virtual Server, the steps to take are:

  • Turn off the image
  • Add a 2nd network adapter to the image, and associate it with the physical adapter in the host machine
  • Start the image, and set the IP address on the 2nd adapter to something that will work on the external network; either dynamically assigned via DHCP, or to a reserved static address

This resolves the IP addressing issue, and if you only need to connect to an external resource by IP address than that’s as much as you need. However, you may still have a DNS problem. I’ve not investigated all scenarios, but I have met cases when, even if the 2nd adapter is configured for with external DNS server, the image still uses its own DNS server for all DNS requests. In this scenario the simplest solution is to configure a forwarder for the virtual DNS server, so that it forwards all DNS requests that it cannot resolve to your known external DNS server. This can be configured with the DNS management snap-in.