Subscribe Now: Feed Icon

Wednesday, November 23, 2011

Clearing ArcGIS Server REST API Cache

Whenever you change a layer in the DB or publish a new server you might notice that the REST API will not automatically update. In order for it to update you might need to clear the REST API cache.

There are several ways to do so:

The default way:

ArcGis Server comes with a REST API admin page, which can be found here:

http://SERVERNAME/ArcGIS/rest/admin

Logging in to this page gives you the Clear Cache Options:

The page has a bunch of options for clearing the catch semi-automatically:

What you need to do is simply click on the "Clear Cache Now" several times (at some version of the Server one time was not enough…).

Disadvantages:

1. You need to have the admin user/password in order to clear the cache
2. The process needs to be done manually.
3. If you have multiple server you will have to do so for each server

 

The token way:

ESRI gives another way which is to use a generated token and then you can simply call a link whenever you want to clear the cache. More on that here (ESRI refers to this method as “the easy way”).

Disadvantages:

1. Different token for each server
2. The process needs to be manually set at each server

 

With Console Application (with code):

The problem with all of these methods is that you can’t really use them to install servers, at my company we have more servers then flies and having to clear the cache after each installation is tedious work that is often forgotten (and when it is forgotten I find myself wasting hours trying to debug the “problem”). So I decided to write a console application that does the clearing of the cache for me. This idea actually came from this forum post, the only problem was that the code didn’t really work for me…

So I tweaked it a bit with WebRequest and the end result is this:

  1. public static string ClearCache(string serverName, string userName, string password)
  2. {
  3.     var result = HttpUtils.PostRequest("http://" + serverName + "/ArcGIS/rest/admin/login",
  4.                             new List<KeyValuePair<string, string>>
  5.                                 {
  6.                                     new KeyValuePair<string, string>("username", userName),
  7.                                     new KeyValuePair<string, string>("password", password),
  8.                                     new KeyValuePair<string, string>("redirect", String.Format("http%3a%2f%2f{0}%2fArcGIS%2frest%2fadmin%2fcache%2fclear", serverName)),
  9.                                 }, String.Format("http://srvp7d-gtm/ArcGIS/rest/admin/login?redirect=http%3a%2f%2f{0}%2fArcGIS%2frest%2fadmin%2fcache%2fclear", serverName));
  10.  
  11.     //The response is in html, only return the response if its not a success
  12.     return result.Contains("Cache Cleared.") ? "Cache Cleared." : result;
  13. }

 

And HttpUtils.PostRequest looks like:

  1. public static string PostRequest(string url, List<KeyValuePair<string, string>> paramters, string referer)
  2. {
  3.     var req = WebRequest.Create(url);
  4.     req.ContentType = "application/x-www-form-urlencoded";
  5.     req.Method = "POST";
  6.  
  7.     var parameters = GetParameters(paramters);
  8.  
  9.     //We need to count how many bytes we're sending.
  10.     var bytes = Encoding.ASCII.GetBytes(parameters);
  11.     req.ContentLength = bytes.Length;
  12.  
  13.     ((HttpWebRequest)req).CookieContainer = new CookieContainer();
  14.     if (!String.IsNullOrEmpty(referer))
  15.         ((HttpWebRequest)req).Referer = referer;
  16.  
  17.     var os = req.GetRequestStream();
  18.     os.Write(bytes, 0, bytes.Length); //Push it out there
  19.     os.Close();
  20.     var resp = req.GetResponse();
  21.     if (resp == null)
  22.         return null;
  23.     var sr = new StreamReader(resp.GetResponseStream());
  24.     return sr.ReadToEnd().Trim();
  25. }

I think that this way is the best since all I need is the server name, the admin user and it’s password. I can do it remotely and I can do it automatically after each deploy. The only thing that is not so good is the using of the clear password (and lets be honest here the next step is putting the call to the console application in a batch file for the development environment and giving that file to the rest of the team so that a hacker…).

Source code can be found at my Codeplex project, here (the code has a few more useful commands like publishing a MSD file, changing the connection of MSD file etc.).

 

Resources:

Clearing the ArcGIS Services Directory cache “the easy way” – ArcGIS Server Blog

Clear cache through code by demand – ArcGis Server Forum

Hanselman: HTTP POSTs and HTTP GETs with WebClient and C# and Faking a PostBack

 

Keywords: ESRI,ArcGIS Server,REST API

IceRocket Tags: ,,

Tuesday, November 15, 2011

ArcObjects: Workspace

This post is the forth post in my ArcObjects series.

As I have written in ArcObjects: Introduction, using ArcObjects is one way of performing CRUD operations against a Spatial DB (with SDE layer on top) and the way to do that is by using the intefaces of WorkspaceClass.

ESRI definition for the Workspace is this:

A Workspace is a container of spatial and non-spatial datasets such as feature classes, raster datasets and tables. It provides methods to instantiate existing datasets and to create new datasets.

Mine is a bit more simple, the WorkspaceClass is the class that does all the “work” within the “space” it is defined to work at. The Space section of the definition can be a DB Sde, File Geodatabase, Cad files and anything else ArcDesktop applications can open. The Work section refers to any basic action that can be done with ArcDesktop applications.

For example: IFeatureWorkspace allows you to create a new Feature Table, open an existing Feature Table and with the help of IFeatureClass perform CRUD operations on that table.

One important note however is that you cannot create a new instance of it, it must be returned for you – the next post will be on getting the workspace.

WorkspaceClass-Object

As you can see the WorkspaceClass implements a lot of interfaces, the good news is you don’t need most of them (I have only found usage for two of them).

What do you need then?

  1. IFeatureWorkspace – probably the most important interface, will allow you to edit features in the Space section
  2. IWorkspaceDomains – allows the creation, deletion of domains (important only if you want to automate the deployment process and using domains)

So how do we use it?

  1. protected internal readonly IFeatureWorkspace _workspace;

  1. protected IFeatureClass GetFeatureClass(string layerName)
  2. {
  3.     return _workspace.OpenFeatureClass(layerName);
  4. }

This actually the only thing you can do with just the IFeatureWorkspace, but if you actually want to do something like  return all the feature in a layer you need to use the IFeatureClass:

  1. private const bool IsRecyclingCursorInGetFeatures = false;

  1. private IQueryFilter GetQueryFilter(string whereClause)
  2. {
  3.     return new QueryFilter {WhereClause = whereClause};
  4. }
  1. protected List<IFeature> GetLayerFeatures(string layerName)
  2. {
  3.     var result = new List<IFeature>();
  4.     var filter = GetQueryFilter(EmptyWhereClause);
  5.     var featureClass = GetFeatureClass(layerName);
  6.     using (var comReleaser = new ComReleaser())
  7.     {
  8.         var cursor = featureClass.Search(filter, IsRecyclingCursorInGetFeatures);
  9.         comReleaser.ManageLifetime(cursor);
  10.  
  11.         var feature = cursor.NextFeature();
  12.         while (feature != null)
  13.         {
  14.             result.Add(feature);
  15.             feature = cursor.NextFeature();
  16.         }
  17.     }
  18.     return result;
  19. }

So what do we have here?

line 4: creates the IQueryFilter – this goes into the where clause of the SQL we will send to DB.

line 5: we get the IFeatureClass of the layer

line 6 and 9: this is important ArcObjects use Com which is a resource, every resource we use must be disposed. At kine 6 we create the disposing class and in line 9 we attach the cursor to that disposing class, when line 17 arrives the using statement will call the Dispose method for ComReleaser  and automatically dispose our cursor. More on cursor and disposing of the resources will be written in a later post.

line 8: creates the cursor that we will use to iterate the rows of the DB, IsRecyclingCursorInGetFeatures defines the way the cursor works (more on that on a later post)

lines 12-16: iterating the data

 

And that’s it.

IceRocket Tags: ,