Tuesday , 16 September 2014
Home » 2010 » May

Monthly Archives: May 2010

Debugging tips for SharePoint

Debugging on SharePoint is much the same as debugging any other ASP.Net application…you can use the same techniques. Here are some of my tips for diagnosing & solving your problems…

Debugging starts with your first line of code

As you start writing some code you need to bear in mind that at some point you will need to debug it. This may mean attaching a debugger (easy) or looking at a crash dump (hard). This means debugging should always be at the back of your mind when writing any code…ask yourself “when this is live how am I going to find out what has gone wrong?”

In practice this means making full use of the features of .Net … System.Diagnosticstry…catchexception logging, etc. One thing in particular to remember is that if you do ever have to look at a crash dump your variable & method names will be in there too. The more descriptive they are the easier it is going to be to analyse the dump. Also bear in mind that the less code in each method the easier it will be to pin-point the location of the error. Les Smith has some good points to make about refactoring…I would add that refactoring making debugging easier!

Use Trace.WriteDebug.Write

This is the first thing I would recommend. Adding these method calls at suitable places in your code can really help to solve problems. Used in conjunction with DebugView these methods can give you great insight to what is happening within your code. Personally I use Trace whenever something unexpected or ‘out of the ordinary’ occurs, normally exceptions, but it could be anything that may help solve a problem. Calls to the Trace methods remain in release code and so will add an overhead to the code execution. I generally use Debug to enable me to see code execution paths during development and as these do nothing in a release build can be used much more liberally.

Using the Trace statements can really help when you cannot attach a debugger (on a live server) to give you more information of what has gone wrong. If you ensure you use try…catch…finally blocks throughout your code, using Trace to log the exception makes it easy to see where the error has occurred (including the call stack) simply by running DebugView on the server.

Use try…catch…finally

When developing ASP.Net controls and WebParts I like to add try…catch blocks when overriding methods likeOnInitOnLoadCreateChildControls and Render. I do this because I don’t what the whole page to fail to render simply because one control has a problem…If the search box control throws an exception, why shouldn’t the rest of the page display? Therefore my Render method would look like this…

protected override void Render(HtmlTextWriter writer)
{
try
{
// Do something to render the control, which may cause an exception

}
catch (Exception ex)
{
Trace.Write(ex);
Trace.WriteLine(HttpContext.Current.Request.Url.ToString());
// Maybe render an error message

}
}

This way if an exception is thrown the page will still render…the user may not get the full functionality of the page, but at least they get something. Essentially wrapping your code in a try…catch block has a negligible hit in terms of performance and so you should look to using them wherever something may throw, even if you just Trace and re-throw the exception. Also you should bear in mind that throwing an exception is a big overhead and should only be used when a real exception has occurred…something you really did not expect and cannot recover from.

Check the SharePoint log files

These will be located in the /12/LOGS folder. The log files contain errors & messages generated by SharePoint. I have to say that generally they don’t give you as much information as you would like (sometimes nothing), but occasionally they point you straight to the problem. Either way you should always check them just in case.

You should also know that you can increase or decrease the amount of logging SharePoint does in Central Administration. Here you can change the verbosity of the logging within different parts of the application. Its not the easiest interface to use, but you can increase the number of messages logged…doing this has solved problems for me in the past.

You change the settings under ‘Logging and Reporting’ in the operations tab…

ASP.NET: Controlling Caching in ASP.NET Web Forms

ASP.NET allows you to cache pages. The means that when the code behind the page runs, it produces HTML, the HTML is sent down to the client, however a copy is stored in the memory of the web server. If the same page is requested again, then the page is retrieved from the cache and the code is not rerun. You have virtually infinite flexibility on controlling when the cache gets flushed.

The most basic caching is implemented by placing this line at the top of your ASPX page:

<%@ OutputCache Duration="3600" VaryByParam="none"%>

What this tells the ASP.NET caching code is to cache the page for one hour.

The full spec for the @OutputCache lines is:

<%@ OutputCache Duration="#ofseconds" Location="Any � Client � Downstream �
Server � None" VaryByControl="controlname" VaryByCustom="browser �
customstring" VaryByHeader="headers" VaryByParam="parametername" %>

Duration is a count in seconds to cache.

Location allows the caching to occur on the server, on the client, on a proxy server in between. The default is Any. If you always want server caching (which seems to me to be the most useful choice), change the line to read:

<%@ OutputCache Duration="3600" Location="Server" VaryByParam="none"%>

VaryByControl is only used by user controls, not on standard web pages. See the .NET documentation for more details.

VaryByCustom=”browser” keeps a different copy of the output for each browser name and major version information. So if you have cloaking by browser version going on (which is easy to implement in .NET), then each separate page will get delivered.

VaryByCustom=”customstring” Allows you to specify a string that will be passed to your code. To make this useful, you must then override the GetVaryByCustomString method in the Global.asax file. For example, place this line in your ASPX file:

<%@ OutputCache Duration="3600" Location="Server" VaryByCustom="Referer" VaryByParam="none"%>

Then in your Global.asax file add the following code:

public override String GetVaryByCustomString(System.Web.HttpContext hcContext, String strCustom)
{
    switch (strCustom)
    {
    case "Referer":
        Uri uriReferrer = hcContext.Request.UrlReferrer;
        String strRet;
        if (uriReferrer != null)
            strRet = uriReferrer.Host;
        else
            strRet = null;
        return strRet;
    default:
        return base.GetVaryByCustomString(hcContext, strCustom);
    }
}

VaryByHeader allows you to cache based off of some field in the HTTP header sent by the client. The classic example is based off the Accept-Language header line.

VaryByParam allows you to cache different versions based off of querystring or post field parameters. So http://www.domain.com/foo.aspx?bar=baz would be cached separately from http://www.domain.com/foo.aspx?bar=bletch

There are also ways of controlling the caching through code.

.NET Tip: Using a Nullable Value Type

How often do your programs grab some data from a database and throw the values returned into local variables without giving the data another thought? I used to, until my programs started throwing exceptions because of nulls in the data. So, what did I do? I checked every field coming back from the database that could possibly be null before storing it in a local variable. Depending upon what your database allows, this could lead to an explosion of code. Here is an example of the type of code that was used to check for a null value before storing it in a local variable. In this case, the BranchCode from a DataReader is being checked:

double BranchCode;
if (dr["BranchCode"] == DBNull.Value)
   BranchCode = -1;
else
    BranchCode = dr["BranchCode"];

This worked, but later in the code the “magic value” of -1 would have to be checked to see whether the variable had a valid BranchCode.

if (BranchCode <> -1)
{
   ...
}

Nullable types allow a cleaner solution to this problem. You can store the data returned from the database into a nullable variable without worry about an exception being thrown at that time. You still may have to perform the check for a valid value later, depending upon exactly how you are using the variable. You can declare a value type variable as nullable using the ? type modifier. Nullable types have two read-only properties that you use to get information about the variable. HasValue returns false if the value is null; otherwise, it returns true. If HasValue returns true, you can access the Value property, which contains the currently stored value. If you attempt to use the Value property when HasValue is false, an exception will be thrown. Here is what the example above would look like using a nullable type:

double? BranchCode;
BranchCode = dr["BranchCode"];

if (BranchCode.HasValue)
{
   switch (BranchCode.Value)
   {
      ...
   }
}

In addition to checking HasValue, you can also just compare the value to null, like this

if (BranchCode != null)
{
   ...
}

You do need to use some caution, however, when using nullable types. Nullable numeric types can be used in comparisons and expressions just like normal numeric expressions. If the nullable variable has a non-null value, everything will work as you would expect. If the nullable variable is null, you need to realize that the result of the expression could be null and make sure that case is handled appropriately.