Working with server contexts


Local (DCOM) connections are only supported for ArcGIS Server versions prior to 10.1.

About server context objects

The ServerContext object provides access to a workspace or "context" in the geographic information system (GIS) server. You can create and manage ArcObjects and other Component Object Model (COM) components within that server context. The ServerContext object is shown in the following illustration:
The ServerObjectManager object provides methods for obtaining information about the GIS server and for creating server contexts for use by an application. The ServerObjectManager object is shown in the following illustration:

Obtaining and releasing server contexts

A server context is obtained using the CreateServerContext method on IServerObjectManager, which returns the IServerContext interface on the server context. The IServerContext interface has methods to help you manage the objects you create within server contexts. The IServerObjectManager and IServerContext methods are shown in the following illustrations:
When developing applications with ArcGIS for Server, all ArcObjects that your application creates and uses reside within a server context. A server context is a reserved space in the server dedicated to a set of running objects. Server objects also reside in a server context. To get a server object, get a reference to its context, then get the server object from the context as shown in the following code example:
[VB.NET]
Dim pServerContext As IServerContext = pServerObjectManager.CreateServerContext("RedlandsMap", "MapServer")
Dim pMapServer As IMapServer = pServerContext.ServerObject
[C#]
IServerContext pServerContext = pServerObjectManager.CreateServerContext(
    "RedlandsMap", "MapServer");
IMapServer pMapServer = pServerContext.ServerObject;
You can also create empty server contexts. You can use an empty context to create ArcObjects on-the-fly in the server to perform ad hoc GIS processing as shown in the following code example:
[VB.NET]
Dim IServerContext As IServerContext = pServerObjectManager.CreateServerContext("", "")
Dim pWorkspaceFactory As IWorkspaceFactory = CType(pServerContext.CreateObject("esriDataSourcesGDB.SdeWorkspaceFactory"), pWorkspaceFactory )
[C#]
IServerContext IServerContext = pServerObjectManager.CreateServerContext("", "");
IWorkspaceFactory pWorkspaceFactory = pServerContext.CreateObject(
    "esriDataSourcesGDB.SdeWorkspaceFactory")as IWorkspaceFactory;
An empty server context is useful when you want to create objects for use by your application in the server but do not require a preconfigured server object. Empty contexts can be used to create any type of object, such as a connection to a workspace as shown in the previous code example. Since server objects are ArcObjects, you can also use empty contexts to create server objects (MapServer, GeocodeServer, GeodataServer, GlobeServer) on-the-fly. Empty server contexts are non-pooled and have high isolation.
When your application is finished working with a server context, it must release it back to the server by calling the ReleaseContext method. If you allow the context to go out of scope without explicitly releasing it, it remains in use and is unavailable to other applications until it is garbage collected. Once a context is released, the application can no longer use objects in that context. This includes objects you have obtained from, or created in, the context. See the following code example:
[VB.NET]
Dim pServerContext As IServerContext = pServerObjectManager.CreateServerContext("RedlandsMap", "MapServer")
Dim pMapServer As IMapServer = pServerContext.ServerObject
' Do something with the object.
pServerContext.ReleaseContext()
[C#]
IServerContext pServerContext = pServerObjectManager.CreateServerContext(
    "RedlandsMap", "MapServer");
IMapServer pMapServer = pServerContext.ServerObject;
// Do something with the object.
pServerContext.ReleaseContext();

Creating objects in the server

Client machines (for example, the Web server machine) require only the Web Application Developer Framework (ADF) runtime be installed to run ArcGIS for Server applications. The Web ADF runtime does not install ArcObjects, so these applications cannot create local ArcObjects. The ArcObjects that your application uses should be created within a server context using the CreateObject method on IServerContext. In previous code examples, CreateObject was used to create an ImageDescription object for use in ExportMapImage.
ArcGIS for Server applications written in .NET should not use New to create local ArcObjects but should always create objects within the server by calling CreateObject on IServerContext as shown in the following code example:
[VB.NET]
' The following is incorrect:
Dim pPoint As IPoint = New Point
' The following is correct:
Dim pPoint As IPoint = CType(pServerContext.CreateObject("esriGeometry.Point"), IPoint)
[C#]
// The following is incorrect: 
IPoint pPoint = new Point();
// The following is correct: 
IPoint pPoint = pServerContext.CreateObject("esriGeometry.Point")as IPoint;
Use CreateObject to create an object for use in your application as shown in the following code example:
[VB.NET]
Dim pPointCollection As IPointCollection = CType(pServerContext.CreateObject("esriGeometry.Polygon"), IPointCollection)
[C#]
IPointCollection pPointCollection = pServerContext.CreateObject(
    "esriGeometry.Polygon")as IPointCollection;
CreateObject returns a proxy to the object that is in the server context. Your application can use the proxy as if the object was created locally within its process. If you call a method on the proxy that returns another object, that object will be in the server context, and your application will be returned a proxy to that object. In the previous code example, if you get a point from the point collection using IPointCollection.Point, the returned point will be in the same context as the point collection.
A proxy object is a local representation of a remote object. The proxy object controls access to the remote object by forcing interaction with the remote object to be via the proxy object. The supported interfaces and methods on a proxy object are the same as those supported by the remote object. You can make method calls on, and get and set properties of, a proxy object as if you were working directly with the remote object.
If you add a point to the point collection using IPointCollection.AddPoint, create that point in the same context as the point collection as shown in the following code example:
[VB.NET]
Dim pPointCollection As IPointCollection = pServerContext.CreateObject("esriGeometry.Polygon")

Dim pPoint As IPoint = CType(pServerContext.CreateObject("esriGeometry.Point"), IPoint)
pPoint.X = 1
pPoint.Y = 1

Dim _missing As Object = Type.Missing

pPointCollection.AddPoint (pPoint, ref _missing , ref _missing )
[C#]
IPointCollection pPointCollection = pServerContext.CreateObject(
    "esriGeometry.Polygon");
IPoint pPoint = (IPoint)(pServerContext.CreateObject("esriGeometry.Point"));
pPoint.X = 1;
pPoint.Y = 1;

object _missing = Type.Missing;

pPointCollection.AddPoint(pPoint, ref _missing, ref _missing);
It is important to understand how your application uses server contexts as it performs its work, because objects that are used together should be in the same context. For example, if you create a point object to use in a spatial selection to query features in a feature class, the point should be in the same context as the feature class. This is important if your application uses more than one server context. It might be necessary to copy objects from one context to another.
Do not directly use objects in a server context with local objects in your application and vice versa. You can indirectly use objects or make copies of them. For example, if you have a point object in a server context, you can get its x,y properties and use them with local objects or use them to create a local point. Do not directly use the point in the server context as the geometry of a local graphic element object for example.
Consider the following code examples. In each example, assume that objects with Remote in their names are objects in a server context:
[VB.NET]
Dim pRemotePoint As IPoint = CType(pServerContext.CreateObject("esriGeometry.Point"), IPoint)
[C#]
IPoint pRemotePoint = (IPoint)(pServerContext.CreateObject("esriGeometry.Point"));
Also, assume objects with Local in their name are objects created locally as in the following code example:
[VB.NET]
Dim pLocalPoint As IPoint = New Point
[C#]
IPoint pLocalPoint = new Point();
You cannot set a local object to a remote object as shown in the following code example:
[VB.NET]
' The following is incorrect:
pLocalPoint = pRemotePoint

' The following is also incorrect:
pLocalElement.Geometry = pRemotePoint
[C#]
// The following is incorrect:
pLocalPoint = pRemotePoint;
// The following is also incorrect:
pLocalElement.Geometry = pRemotePoint;
Do not set a local object or a property of a local object, as an object obtained from a remote object, as shown in the following code example:
[VB.NET]
' The following is incorrect:
pLocalPoint = pRemotePointCollection.Point(0)
[C#]
// The following is incorrect:
pLocalPoint = pRemotePointCollection.get_Point(0);
When calling a method on a remote object, do not pass in local objects as parameters, as shown in the following code example:
[VB.NET]
' The following is incorrect:
pRemoteWorkspace = pRemoteWorkspaceFactory.Open(pLocalPropertySet, 0)
[C#]
// The following is incorrect:
pRemoteWorkspace = pRemoteWorkspaceFactory.Open(pLocalPropertySet, 0);
You can get simple data types (double, long, string, and so on) that are passed by value from a remote object and use them as properties of a local object as shown in the following code example:
[VB.NET]
' The following is correct:
pLocalPoint.X = pRemotePoint.X
pLocalPoint.Y = pRemotePoint.Y
[C#]
// The following is correct:
pLocalPoint.X = pRemotePoint.X;
pLocalPoint.Y = pRemotePoint.Y;
The SaveObject and LoadObject methods allow you to serialize objects in the server context to a string, then deserialize them back into objects. These methods also allow you to copy objects between contexts. Any object that supports IPersistStream can be saved and loaded using these methods. For example, in an application that uses the MapServer object for mapping and the GeocodeServer object for geocoding, the GeocodeServer and MapServer will be running in different contexts.
If you use the GeocodeServer object to locate an address and you want to draw the resulting point that GeocodeAddress returns on your map, copy the point into the MapServer context as shown in the following code example:
[VB.NET]
Dim pServerContext As IServerContext = pSOM.CreateServerContext("RedlandsMap", "MapServer")
Dim pServerContext2 As IServerContext = pSOM.CreateServerContext("RedlandsGeocode", "GeocodeServer")
Dim pGCServer As IGeocodeServer = pServerContext2.ServerObject

Dim pPropertySet As IPropertySet = pServerContext2.CreateObject("esriSystem.PropertySet")
pPropertySet.SetProperty ("Street", "380 New York St")

Dim pResults As IPropertySet = pGCServer.GeocodeAddress(pPropertySet, Nothing)
Dim pPoint As IPoint = pResults.GetProperty("Shape")

' Copy the point to the Map's server context.
Dim sPoint As String = pServerContext2.SaveObject(pPoint)
Dim pPointCopy As IPoint = CType(pServerContext.LoadObject(sPoint), IPoint)

pServerContext2.ReleaseContext()

' Add the point as a graphic to the map description and redraw the map.

pServerContext.ReleaseContext()
[C#]
IServerContext pServerContext = pSOM.CreateServerContext("RedlandsMap", "MapServer");
IServerContext pServerContext2 = pSOM.CreateServerContext("RedlandsGeocode", 
    "GeocodeServer");
IGeocodeServer pGCServer = pServerContext2.ServerObject;
IPropertySet pPropertySet = pServerContext2.CreateObject("esriSystem.PropertySet");
pPropertySet.SetProperty("Street", "380 New York St");
IPropertySet pResults = pGCServer.GeocodeAddress(pPropertySet, null);
IPoint pPoint = (IPoint)pResults.GetProperty("Shape");
// Copy the point to the Map's server context.
string sPoint = pServerContext2.SaveObject(pPoint);
IPoint pPointCopy = (IPoint)(pServerContext.LoadObject(sPoint));
pServerContext2.ReleaseContext();
// Add the point as a graphic to the map description and redraw the map.
pServerContext.ReleaseContext();
PropertySet is a generic class that is used to hold a set of properties. The properties of PropertySet are stored as name/value pairs. Examples of using PropertySet are holding the properties required for opening a Spatial Database Engine (SDE) workspace and geocoding an address.
The following illustration shows the use of SaveObject and LoadObject to copy objects between server contexts. The illustration is numbered 1 through 3 and described as follows:
  1. The client application gets or creates an object in a server context.
  2. The application uses the SaveObject method on the object's context to serialize the object as a string that is held in the application's session state.
  3. The client application gets a reference to another server context and calls the LoadObject method, passing in the string created by SaveObject. LoadObject creates an instance of the object in the new server context.

Managing objects in a server context

A server context contains an object dictionary that serves as a convenient place to store references to commonly used objects. You can use the server context's object dictionary to keep track of objects during the life span of the context. You can also use the context's dictionary as a place to store objects that you create within the context. The dictionary is valid only as long as you hold on to the server context and it is emptied when you release the context. You can use this dictionary to share objects created within a context between different parts of your application that have access to the context.
For example, if your application makes repeated use of a geometry object across requests, rather than creating the geometry object over and over again, your application can store the geometry object in the context's dictionary so you can use it multiple times without recreating it. This is shown in the following code example:
[VB.NET]
Dim pPointCollection As IPointCollection = pServerContext.CreateObject("esriGeometry.Polygon")

pServerContext.SetObject ("myPoly", pPointCollection)
Dim pPoly As IPolygon = pServerContext.GetObject("myPoly")
[C#]
IPointCollection pPointCollection = pServerContext.CreateObject(
    "esriGeometry.Polygon");
pServerContext.SetObject("myPoly", pPointCollection);
IPolygon pPoly = (IPolygon)pServerContext.GetObject("myPoly");
You can add objects to, and retrieve objects from, the dictionary using the SetObject and GetObject methods, respectively. An object that is set in the context is available until it is removed (by calling Remove or RemoveAll) or until the context is released. Use the Remove and RemoveAll methods to remove an object from a context that has been set using SetObject. Once an object is removed, a reference to it can no longer be obtained using GetObject as shown in the following code example:
[VB.NET]
pServerContext.Remove ("myPoly")
[C#]
pServerContext.Remove("myPoly");
If you do not explicitly call Remove or RemoveAll, you cannot get references to objects set in the context after the context has been released.

Writing output

When your application performs operations using ArcObjects running in server contexts, those operations might need to write out data to disk. For example, the ExportMapImage method on a map server object writes images to disk and the CheckOut method on a geodata server object writes personal geodatabases to disk. Another example of an application that needs to write data is an application that uses geoprocessing objects to create shapefiles. Those shapefiles must be written to disk so they can be downloaded. These types of files need to be cleaned up by the server eventually. To ensure this occurs, your applications should write their output to a server directory.
To get the directory of a GIS server, call GetServerDirectoryInfos on the IServerObjectManager interface on the server object manager (SOM). For your files to be cleaned up when written into that server directory, they must follow a file naming convention. The GIS server deletes all files in a server directory that are prefixed with _ags_. Any file written to an output directory that is not prefixed with _ags_ will not be cleaned by the GIS server.
The IServerDirectoryInfo methods are shown in the following illustration:
The following code example shows how to use the GetServerDirectoryInfos method on IServerObjectManager to get a server directory and create a personal geodatabase. This code creates two geodatabases, one named with the _ags_ prefix so it is cleaned by the GIS server, and one named without the _ags_ prefix so it is not cleaned by the GIS server.
[VB.NET]
Dim pServerContext As IServerContext = pSOM.CreateServerContext("", "")

Dim pWSF As IWorkspaceFactory = Ctype(pServerContext.CreateObject("esriDataSourcesGDB.AccessWorkspaceFactory"), IWorkspaceFactory)

Dim pEnumSDI As IEnumServerDirectoryInfo = pSOM.GetServerDirectoryInfos
Dim pSDI As IServerDirectoryInfo = pEnumSDI.Next

Dim pProps As IPropertySet = CType(pServerContext.CreateObject("esriSystem.PropertySet"), IPropertySet)

' The following database will be cleaned by the GIS server:
pProps.SetProperty ("DATABASE", pSDI.Path & "\_ags_db1.mdb")
pWSF.Create (pSDI.Path, "_ags_db1", pProps, 0)

' The following database will not be cleaned by the GIS server:
pProps.SetProperty ("DATABASE", pSDI.Path & "\db2.mdb")
pWSF.Create (pSDI.Path, "db2", pProps, 0)
[C#]
IServerContext pServerContext = pSOM.CreateServerContext("", "");
IWorkspaceFactory pWSF = (IWorkspaceFactory)(pServerContext.CreateObject(
    "esriDataSourcesGDB.AccessWorkspaceFactory"));
IEnumServerDirectoryInfo pEnumSDI = pSOM.GetServerDirectoryInfos;
IServerDirectoryInfo pSDI = pEnumSDI.Next();
IPropertySet pProps = (IPropertySet)(pServerContext.CreateObject(
    "esriSystem.PropertySet"));
// The following database will be cleaned by the GIS server:
pProps.SetProperty("DATABASE", pSDI.Path + "\\_ags_db1.mdb");
pWSF.Create(pSDI.Path, "_ags_db1", pProps, 0);
// The following database will not be cleaned by the GIS server:
pProps.SetProperty("DATABASE", pSDI.Path + "\\db2.mdb");
pWSF.Create(pSDI.Path, "db2", pProps, 0);

Working with ArcGIS for Server extensions

If your server object container (SOC) machine has a license for the Spatial, 3D, Network, or Data Interoperability extension for ArcGIS for Server, your applications can use the functionality that is unlocked by that license.
You do not need to make explicit calls to get a license when you want to use an object that requires a license. All you need to do is create the object on the server and use it. If the SOC machine is not licensed, any method calls you make on the object fail.