diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/StringHtmlEscapingPointcutAdvisor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/StringHtmlEscapingPointcutAdvisor.java
index 7be110622c34ec122005d93896807598bfc33d7f..cafe5c07e521a8f49e9df1bb68ab18d754ec3f0f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/StringHtmlEscapingPointcutAdvisor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/StringHtmlEscapingPointcutAdvisor.java
@@ -16,9 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server;
 
-import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
-import java.util.WeakHashMap;
 
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
@@ -31,6 +29,8 @@ import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.utilities.ReflectingStringEscaper;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientService;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TypedTableResultSet;
 
 /**
  * The advisor for automatically escaping HTML strings in the values returned by the
@@ -80,13 +80,31 @@ public class StringHtmlEscapingPointcutAdvisor extends DefaultPointcutAdvisor
                 return false;
             }
 
-            if (method.getName().equals("getApplicationInfo"))
+            if (method.getReturnType() == Void.TYPE)
             {
-                escapeLog.info("Asked to handle getApplicationInfo");
                 return false;
             }
 
-            if (method.getReturnType() == Void.TYPE)
+            // This is handled in the cache manager
+            if (method.getReturnType() == TypedTableResultSet.class)
+            {
+                return false;
+            }
+
+            // This is handled in the cache manager
+            if (method.getReturnType() == ResultSet.class)
+            {
+                return false;
+            }
+
+            // Don't need to escape this method
+            if ("getLastModificationState".equals(method.getName()))
+            {
+                return false;
+            }
+
+            // This is handled in the cache manager
+            if (method.getReturnType() == ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetWithEntityTypes.class)
             {
                 return false;
             }
@@ -103,9 +121,6 @@ public class StringHtmlEscapingPointcutAdvisor extends DefaultPointcutAdvisor
     public static class StringHtmlEscapingPointcutAdvisorMethodInterceptor implements
             MethodInterceptor
     {
-        private final WeakHashMap<Object, WeakReference<Object>> alreadyEscapedObjects =
-                new WeakHashMap<Object, WeakReference<Object>>();
-
         /**
          * Get the session token and any guarded parameters and invoke the guards on those
          * parameters.
@@ -114,32 +129,34 @@ public class StringHtmlEscapingPointcutAdvisor extends DefaultPointcutAdvisor
         {
             Object result = methodInvocation.proceed();
 
-            // check if the object has already been escaped
-            synchronized (this)
-            {
-                WeakReference<Object> alreadyEscaped = alreadyEscapedObjects.get(result);
-                if (alreadyEscaped != null)
-                {
-                    escapeObject(methodInvocation, result);
-                    alreadyEscapedObjects.put(result, new WeakReference<Object>(result));
-                }
-            }
+            result = escapeObject(methodInvocation, result);
 
             return result;
         }
 
-        private void escapeObject(MethodInvocation methodInvocation, Object result)
+        private Object escapeObject(MethodInvocation methodInvocation, Object unescapedResult)
         {
-            escapeLog.info(methodInvocation.getMethod().getName() + " converting   " + result);
-            if (result instanceof String)
+            Object result = unescapedResult;
+            escapeLog.info(methodInvocation.getMethod().getName() + " converting   "
+                    + unescapedResult);
+            if (unescapedResult instanceof String)
             {
-                StringEscapeUtils.escapeHtml((String) result);
+                if ("getExportTable".equals(methodInvocation.getMethod().getName()))
+                {
+                    result = StringEscapeUtils.unescapeHtml((String) unescapedResult);
+                } else
+                {
+                    // Do we need to escape strings in general?
+                    // StringEscapeUtils.escapeHtml((String) unescapedResult);
+                }
             } else
             {
                 // Escape the result objects
-                ReflectingStringEscaper.escapeDeep(result);
+                ReflectingStringEscaper.escapeDeep(unescapedResult);
             }
-            escapeLog.info(methodInvocation.getMethod().getName() + " converted to " + result);
+            escapeLog.info(methodInvocation.getMethod().getName() + " converted to "
+                    + unescapedResult);
+            return result;
         }
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java
index 5ec4f76c4b5871a566cfc6aa0a3086a96bb80528..a99e11f2b87e402571d70445342286ca5ef45237 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java
@@ -35,6 +35,7 @@ import ch.rinn.restrictions.Private;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.shared.basic.AlternativesStringFilter;
+import ch.systemsx.cisd.common.utilities.ReflectingStringEscaper;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ColumnDistinctValues;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CustomFilterInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridColumnFilterInfo;
@@ -70,16 +71,17 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
     @Private
     static final int MAX_DISTINCT_COLUMN_VALUES_SIZE = 50;
 
-    private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, CachedResultSetManager.class);
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            CachedResultSetManager.class);
 
     private static final GridCustomColumnInfo translate(GridCustomColumn columnDefinition)
     {
         return new GridCustomColumnInfo(columnDefinition.getCode(), columnDefinition.getName(),
                 columnDefinition.getDescription(), columnDefinition.getDataType());
     }
-    
-    private static <T> String getOriginalValue(IColumnDefinition<T> definition, final GridRowModel<T> row)
+
+    private static <T> String getOriginalValue(IColumnDefinition<T> definition,
+            final GridRowModel<T> row)
     {
         Comparable<?> value = definition.tryGetComparableValue(row);
         return value == null ? "" : value.toString();
@@ -88,16 +90,17 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
     static interface IColumnCalculator
     {
         /**
-         * Calculates the values of the specified custom column definition by using specified data and
-         * specified column definitions. In case of an error the column value is an error message.
+         * Calculates the values of the specified custom column definition by using specified data
+         * and specified column definitions. In case of an error the column value is an error
+         * message.
          * 
          * @param errorMessagesAreLong if <code>true</code> a long error message will be created.
          */
         public <T> List<PrimitiveValue> evalCustomColumn(List<T> data,
                 GridCustomColumn customColumn, Set<IColumnDefinition<T>> availableColumns,
-                boolean errorMessagesAreLong);   
+                boolean errorMessagesAreLong);
     }
-    
+
     private static final class Column
     {
         private final GridCustomColumn columnDefinition;
@@ -139,13 +142,14 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
         private final IColumnCalculator columnCalculator;
 
         private final List<TableModelColumnHeader> headers;
-        
-        private final List<IColumnDefinition<T>> headerColumnDefinitions = new ArrayList<IColumnDefinition<T>>();
-        
+
+        private final List<IColumnDefinition<T>> headerColumnDefinitions =
+                new ArrayList<IColumnDefinition<T>>();
+
         private Map<String, Column> calculatedColumns = new HashMap<String, Column>();
 
-        TableData(List<T> originalData, List<TableModelColumnHeader> headers, ICustomColumnsProvider customColumnsProvider,
-                IColumnCalculator columnCalculator)
+        TableData(List<T> originalData, List<TableModelColumnHeader> headers,
+                ICustomColumnsProvider customColumnsProvider, IColumnCalculator columnCalculator)
         {
             this.originalData = originalData;
             this.headers = headers;
@@ -422,7 +426,7 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
 
     // all cache access should be doen in a monitor (synchronized clause)
     private final Map<K, TableData<?>> cache = new HashMap<K, TableData<?>>();
-    
+
     private final XMLPropertyTransformer xmlPropertyTransformer = new XMLPropertyTransformer();
 
     private final IColumnCalculator columnCalculator;
@@ -512,7 +516,8 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
             ITableDataProvider dataProvider =
                     TableDataProviderFactory.createDataProvider(rows,
                             new ArrayList<IColumnDefinition<T>>(availableColumns));
-            List<Integer> indices = GridExpressionUtils.applyCustomFilter(dataProvider, customFilterInfo);
+            List<Integer> indices =
+                    GridExpressionUtils.applyCustomFilter(dataProvider, customFilterInfo);
             filteredRows = new ArrayList<GridRowModel<T>>();
             for (Integer index : indices)
             {
@@ -630,6 +635,19 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
 
     public final <T> IResultSet<K, T> getResultSet(final String sessionToken,
             final IResultSetConfig<K, T> resultConfig, final IOriginalDataProvider<T> dataProvider)
+    {
+        // Get the raw result set
+        IResultSet<K, T> cachedResultSet =
+                getRawResultSet(sessionToken, resultConfig, dataProvider);
+
+        return cachedResultSet;
+    }
+
+    /**
+     * Raw handling of retrieving the result set from the cache -- no HTML escaping is applied.
+     */
+    private final <T> IResultSet<K, T> getRawResultSet(final String sessionToken,
+            final IResultSetConfig<K, T> resultConfig, final IOriginalDataProvider<T> dataProvider)
     {
         assert resultConfig != null : "Unspecified result configuration";
         assert dataProvider != null : "Unspecified data retriever";
@@ -665,11 +683,19 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se
         List<T> rows = dataProvider.getOriginalData();
         List<TableModelColumnHeader> headers = dataProvider.getHeaders();
         xmlPropertyTransformer.transformXMLProperties(rows);
-        TableData<T> tableData = new TableData<T>(rows, headers, customColumnsProvider, columnCalculator);
+        TableData<T> tableData =
+                new TableData<T>(rows, headers, customColumnsProvider, columnCalculator);
+
+        // Escape the values
+        for (T row : rows)
+        {
+            ReflectingStringEscaper.escapeDeep(row);
+        }
+
         addToCache(dataKey, tableData);
         return calculateSortAndFilterResult(sessionToken, tableData, resultConfig, dataKey);
     }
-    
+
     private synchronized <T> void addToCache(K dataKey, TableData<T> tableData)
     {
         cache.put(dataKey, tableData);