Saturday, July 24, 2010

Handling SOAP fault exceptions from a WCF service

I was expecting that using catch (Exception ex) would catch the fault (it actually does) and it would be able to retrieve the fault information (not the case). This article showed me how to do it: use catch(FaultException ex).

Actually, I added catch clauses for both the generic exception and the fault exception. Don't forget the generic exception goes after the fault exception, otherwise the fault exception will never get caught.

Friday, July 23, 2010

ArcGIS Server Context Usage Timeout Interval error

An application that uses ArcObjects was throwing an exception and after some digging, everything was pointing to a problem on ArcGIS Server 9.3.1. The logs showed the error:

"The context has been automatically released because the context usage timeout interval has elapsed"

This KB article indicated that I had to modify the
EngineContextTimeout setting in the server.dat file. For some reason, the value in the file was 5, instead of the default 600. It would certainly be nice if the exceptions thrown by ArcGIS Server contained useful information.

Wednesday, July 14, 2010

Access the content page from the paster page

Have you ever wondered how to make the Content page respond to events in the master page? There is a great article here!

Wednesday, July 7, 2010

AJAX Panel vs. Page Methods

A coworker sent this article to me http://encosia.com/2007/07/11/why-aspnet-ajax-updatepanels-are-dangerous/. I have used both technologies (check out ajax.net), and personally, I think Page Methods work great. Just keep in mind that if you use Page Methods, it's better to use Dojo or JQuery to access the DOM.

I have to say that my first thought was that Page Methods were kind of a hack, because they work around the Postback model. Maybe they're just the best of two worlds (client/server side). In my case, I prefer to use Page Methods when a website contains a lot of JavaScript code, and UpdatePanels when server side development is heavy.

,

Thursday, July 1, 2010

Converting an object array into a DataTable using LINQ

This is not possible with the current implementation of LINQ, but it is really easy to extend LINQ to support it. I found how to do it here http://blogs.msdn.com/b/aconrad/archive/2007/09/07/science-project.aspx. The method you need is CopyToDataTable, and the code that supports it is (copied from the link above):


public static class DataSetLinqOperators
{
public static DataTable CopyToDataTable(this IEnumerable source)
{
return new ObjectShredder().Shred(source, null, null);
}

public static DataTable CopyToDataTable(this IEnumerable source,
DataTable table, LoadOption? options)
{
return new ObjectShredder().Shred(source, table, options);
}

}

public class ObjectShredder
{
private FieldInfo[] _fi;
private PropertyInfo[] _pi;
private Dictionary _ordinalMap;
private Type _type;

public ObjectShredder()
{
_type = typeof(T);
_fi = _type.GetFields();
_pi = _type.GetProperties();
_ordinalMap = new Dictionary();
}

public DataTable Shred(IEnumerable source, DataTable table, LoadOption? options)
{
if (typeof(T).IsPrimitive)
{
return ShredPrimitive(source, table, options);
}


if (table == null)
{
table = new DataTable(typeof(T).Name);
}

// now see if need to extend datatable base on the type T + build ordinal map
table = ExtendTable(table, typeof(T));

table.BeginLoadData();
using (IEnumerator e = source.GetEnumerator())
{
while (e.MoveNext())
{
if (options != null)
{
table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options);
}
else
{
table.LoadDataRow(ShredObject(table, e.Current), true);
}
}
}
table.EndLoadData();
return table;
}

public DataTable ShredPrimitive(IEnumerable source, DataTable table, LoadOption? options)
{
if (table == null)
{
table = new DataTable(typeof(T).Name);
}

if (!table.Columns.Contains("Value"))
{
table.Columns.Add("Value", typeof(T));
}

table.BeginLoadData();
using (IEnumerator e = source.GetEnumerator())
{
Object[] values = new object[table.Columns.Count];
while (e.MoveNext())
{
values[table.Columns["Value"].Ordinal] = e.Current;

if (options != null)
{
table.LoadDataRow(values, (LoadOption)options);
}
else
{
table.LoadDataRow(values, true);
}
}
}
table.EndLoadData();
return table;
}

public DataTable ExtendTable(DataTable table, Type type)
{
// value is type derived from T, may need to extend table.
foreach (FieldInfo f in type.GetFields())
{
if (!_ordinalMap.ContainsKey(f.Name))
{
DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name]
: table.Columns.Add(f.Name, f.FieldType);
_ordinalMap.Add(f.Name, dc.Ordinal);
}
}
foreach (PropertyInfo p in type.GetProperties())
{
if (!_ordinalMap.ContainsKey(p.Name))
{
DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name]
: table.Columns.Add(p.Name, p.PropertyType);
_ordinalMap.Add(p.Name, dc.Ordinal);
}
}
return table;
}

public object[] ShredObject(DataTable table, T instance)
{

FieldInfo[] fi = _fi;
PropertyInfo[] pi = _pi;

if (instance.GetType() != typeof(T))
{
ExtendTable(table, instance.GetType());
fi = instance.GetType().GetFields();
pi = instance.GetType().GetProperties();
}

Object[] values = new object[table.Columns.Count];
foreach (FieldInfo f in fi)
{
values[_ordinalMap[f.Name]] = f.GetValue(instance);
}

foreach (PropertyInfo p in pi)
{
values[_ordinalMap[p.Name]] = p.GetValue(instance, null);
}
return values;
}
}

Thanks a lot to the author of this code!