Hello,
I'm trying to load a IFeatureLayer from a FeatureServer in a ArcGIS Engine 10.3 Application, but I always get a "System.Runtime.InteropServices.COMException" Error Message. (Line is marked with an Error Comment).
What is the Problem of getting the Layers from the Server?
Thank You very much for your help.
Public Shared Function GetAGSFeatureLayer(ByVal sURL As String) As IFeatureLayer
Dim pAGSConnectionFactory As IAGSServerConnectionFactory
Dim pConnectionProps As IPropertySet
Dim pAGSConnection As IAGSServerConnection
Dim enumServerObjectName As IAGSEnumServerObjectName
Dim pServerObjectName As IAGSServerObjectName3
Dim pName As IName
Dim pObject As Object
Dim pServerSymbolOutputOptions As IServerSymbolOutputOptions
Dim pGraphicFeatureLayers As IGraphicFeatureLayers
Dim pGraphicFeatureLayer As IGraphicFeatureLayer2
Dim pGraphicFeatureServer As IGraphicFeatureServer
Try
pConnectionProps = New PropertySet
pConnectionProps.SetProperty("URL", sURL)
pAGSConnectionFactory = New AGSServerConnectionFactory
pAGSConnection = pAGSConnectionFactory.Open(pConnectionProps, 0)
enumServerObjectName = pAGSConnection.ServerObjectNames
enumServerObjectName.Reset()
pServerObjectName = enumServerObjectName.Next
Do Until pServerObjectName Is Nothing
If pServerObjectName.Type.Equals("FeatureServer", StringComparison.OrdinalIgnoreCase) Then
pName = pServerObjectName
pObject = pName.Open
If TypeOf pObject Is IGraphicFeatureServer Then
pServerSymbolOutputOptions = New ServerSymbolOutputOptions
pServerSymbolOutputOptions.ConvertLabelExpressions = False
pServerSymbolOutputOptions.PictureOutputType = esriServerPictureOutputType.esriServerPictureOutputAsPNG
pGraphicFeatureServer = pObject
pGraphicFeatureLayers = pGraphicFeatureServer.GetLayers(pServerSymbolOutputOptions) 'ERROR
If pGraphicFeatureLayers.Count > 0 Then
For i As Integer = 0 To pGraphicFeatureLayers.Count - 1
pGraphicFeatureLayer = pGraphicFeatureLayers.Element(i)
If TypeOf pGraphicFeatureLayer Is IFeatureLayer Then
Return pGraphicFeatureLayer
End If
Next
End If
End If
End If
pServerObjectName = enumServerObjectName.Next
Loop
Catch ex As Exception
logger.Error("GetAGSFeatureLayer", ex)
End Try
Return Nothing
End Function
Solved! Go to Solution.
Got it:
Snippet
Public Shared Function GetAGSFeatureLayer(ByVal sURL As String) As IFeatureLayer Dim pAGSConnectionFactory As IAGSServerConnectionFactory Dim pConnectionProps As IPropertySet Dim pAGSConnection As IAGSServerConnection Dim enumServerObjectName As IAGSEnumServerObjectName Dim pServerObjectName As IAGSServerObjectName3 Dim pLayerFactory As ILayerFactory Dim pEnumLayer As IEnumLayer Dim pLayer As ILayer Dim pCurrentLayer As ILayer Dim pCompositeLayer As ICompositeLayer Try pConnectionProps = New PropertySet pConnectionProps.SetProperty("URL", sURL) pAGSConnectionFactory = New AGSServerConnectionFactory pAGSConnection = pAGSConnectionFactory.Open(pConnectionProps, 0) enumServerObjectName = pAGSConnection.ServerObjectNames enumServerObjectName.Reset() pServerObjectName = enumServerObjectName.Next Do Until pServerObjectName Is Nothing If pServerObjectName.Type.Equals("FeatureServer", StringComparison.OrdinalIgnoreCase) Then pLayerFactory = New FeatureServerLayerFactory pEnumLayer = pLayerFactory.Create(pServerObjectName) pLayer = pEnumLayer.Next() Do Until pLayer Is Nothing If TypeOf pLayer Is ICompositeLayer Then pCompositeLayer = pLayer For i As Integer = 0 To pCompositeLayer.Count - 1 pCurrentLayer = pCompositeLayer.Layer(i) If TypeOf pCurrentLayer Is IFeatureLayer Then Return DirectCast(pCurrentLayer, IFeatureLayer) End If Next End If pLayer = pEnumLayer.Next() Loop End If pServerObjectName = enumServerObjectName.Next Loop Catch ex As Exception logger.Error("GetAGSFeatureLayer", ex) End Try Return Nothing End Function
The code sample here below shows how to add a feature service to ArcMap using ArcObjects (click on the image below to enlarge the image):
Thank you, very much, but in your example you create your own new layer.
Isn't it possible to get the layer with it's symbology/renderer from the Feature-Service?
Mickey,
Yes, that is correct. I do create my own new layer to add to ArcMap. One would definitely need an instance of a new layer object to hold the properties of the incoming feature service data, so there is definitely a need to create that new layer.
However, in order to symbolize and display that new layer the exact same way it was being displayed on the server (and I believe this is your question), you would simply not assign a renderer to it. Thus, in the code I provided earlier, all you'd have to do is to comment out the "renderer" part of the code. This should allow the display of the layer in its "original" form. In this case, the original renderer that was used for the feature service layer on the server (the REST endpoint) would automatically be utilized by ArcMap to render the layer.
Hello Sami,
thank you, that's what I was looking for. But there are two more things I need to know:
If I load a Feature Service in ArcMap, the Layers have Layernames which are the Name of the Feature-Class in their SDE. In ArcObjects the FC-Names are Numbers. Furthermore the Layer have set a minimum scale.
Where do I find the FC-Name and minimum Scale in ArcObjects?
The feature class name can be accessed via the IFeatureClass.AliasName property:
http://resources.arcgis.com/en/help/arcobjects-net/componenthelp/index.html#//0025000002qs000000
The layer's minimum scale may be accessed via the ILayer.MinimumScale property:
http://resources.arcgis.com/en/help/arcobjects-net/componenthelp/index.html#//0012000006z1000000
A good book on ArcObjects development that you might find useful is Beginning ArcGIS for Desktop Development using .NET, by Pouria Amirian (2013).
Sorry, my english is not very good, maybe you didn't understand me right:
I'm writing an ArcGIS Engine Application which should load Feature-Services the same way as ArcMap. And if I load a Feature-Service in ArcMap, ArcMap creates Layers with a Layername, a Symbology and a minimum scale.
Now If I use your code from above in my ArcGIS Engine App, I only have a Feature-Class. The name and the alias-name of this Feature-Class is a number (e.g. 0). And if I create a new Layer and set the datasource, the Layer has no minimum scale.
So, my question is: how does ArcMap gets the Layername and minimum scale from the Feature-Service? Your code from above does not answer this question.
Thank you very much.
Any suggestions so far?
Got it:
Snippet
Public Shared Function GetAGSFeatureLayer(ByVal sURL As String) As IFeatureLayer Dim pAGSConnectionFactory As IAGSServerConnectionFactory Dim pConnectionProps As IPropertySet Dim pAGSConnection As IAGSServerConnection Dim enumServerObjectName As IAGSEnumServerObjectName Dim pServerObjectName As IAGSServerObjectName3 Dim pLayerFactory As ILayerFactory Dim pEnumLayer As IEnumLayer Dim pLayer As ILayer Dim pCurrentLayer As ILayer Dim pCompositeLayer As ICompositeLayer Try pConnectionProps = New PropertySet pConnectionProps.SetProperty("URL", sURL) pAGSConnectionFactory = New AGSServerConnectionFactory pAGSConnection = pAGSConnectionFactory.Open(pConnectionProps, 0) enumServerObjectName = pAGSConnection.ServerObjectNames enumServerObjectName.Reset() pServerObjectName = enumServerObjectName.Next Do Until pServerObjectName Is Nothing If pServerObjectName.Type.Equals("FeatureServer", StringComparison.OrdinalIgnoreCase) Then pLayerFactory = New FeatureServerLayerFactory pEnumLayer = pLayerFactory.Create(pServerObjectName) pLayer = pEnumLayer.Next() Do Until pLayer Is Nothing If TypeOf pLayer Is ICompositeLayer Then pCompositeLayer = pLayer For i As Integer = 0 To pCompositeLayer.Count - 1 pCurrentLayer = pCompositeLayer.Layer(i) If TypeOf pCurrentLayer Is IFeatureLayer Then Return DirectCast(pCurrentLayer, IFeatureLayer) End If Next End If pLayer = pEnumLayer.Next() Loop End If pServerObjectName = enumServerObjectName.Next Loop Catch ex As Exception logger.Error("GetAGSFeatureLayer", ex) End Try Return Nothing End Function