Hi, I'm facing an issue with ArcGIS Runtime (tested in both version 100.15 and 200.5) while working with a WFS Layer hosted on a MapServer.
When attempting to use the WFS layer, I encounter this exception:
ArcGISRuntimeException: Geodatabase data type mismatch: my_field
Upon investigation, I found that the problematic field (my_field) has the following characteristics:
<complexType name="my_type">
<complexContent>
<extension base="gml:AbstractFeatureType">
<sequence>
{other Fields}
<element name="my_field" minOccurs="0" type="string"/>
{other Fields}
</sequence>
</extension>
</complexContent>
</complexType>
The challenge is that the values in this field are mixed: sometimes just numeric, sometimes strings. The field should always be treated as a string to accommodate the varying data types.
Is there a way to configure or force the field to always be interpreted as a string in the Runtime SDK?
Any help or insights would be greatly appreciated. Thanks in advance!
Solved! Go to Solution.
We were able to resolve the problem via email, but I wanted to share a summary here in case someone else has a similar problem in the future.
It turned out that this FeatureType has fields of type “gml:TimeInstantType”, but WFSFeatureTable's XSD parser does not support GML temporal schemas and gives up parsing the DescribeFeatureType response. Without understanding the original schema, the table falls back to guessing the field type based on the first feature. In this case, the first feature had a numeric-looking value for the field ("111"), so WFSFeatureTable guessed that it should be an integer column. When later GetFeature responses contained rows with non-numeric strings for this field, they could not be inserted into the table.
Luckily, there was a workaround. In Maps SDK 200.5+ you can implement an IHttpMessageInterceptor that listens for DescribeFeatureType responses and replaces the unsupported “gml:TimeInstantType” type with something more compatible. Here is what that implementation would look like:
class DescribeFeatureTypeRewriter : IHttpMessageInterceptor
{
public async Task<HttpResponseMessage> SendAsync(HttpMessageInvoker invoker, HttpRequestMessage message, CancellationToken cancellationToken)
{
var response = await invoker.SendAsync(message, cancellationToken);
if (message.RequestUri.Query.Contains("=DescribeFeatureType") && response.IsSuccessStatusCode)
{
// This is an XML schema returned by WFS DescribeFeatureType response.
// Edit it to replace the unsupported "gml:TimeInstantType" with "dateTime" before passing it to Runtime.
// Most of the time both are represented by ISO 8601 strings, so this is a broadly compatible change.
var xsdString = await response.Content.ReadAsStringAsync();
xsdString = xsdString.Replace("gml:TimeInstantType", "dateTime");
response.Content = new StringContent(xsdString);
}
return response;
}
}
And here is how you would hook up the interceptor on startup:
ArcGISRuntimeEnvironment.Initialize(
config => config.ConfigureHttp(
httpConfig => httpConfig.UseHttpMessageInterceptor(new DescribeFeatureTypeRewriter())
)
);
Hello Tim! Normally WFSFeatureTable is able to derive the table schema correctly by examining the XSD returned by DescribeFeatureType response. However, I have sometimes seen edge-cases where it cannot load or parse the XSD and has to guess based on values in the first GetFeature response.
I think that's what might have happened here, but I do not have enough information to diagnose the problem. Would you be able to share the URL of this service, or a full example of the GetCapabilities/DescribeFeatureType/GetFeature responses? You can also email me at mstefarov@esri.com. I would be glad to look deeper into this.
We were able to resolve the problem via email, but I wanted to share a summary here in case someone else has a similar problem in the future.
It turned out that this FeatureType has fields of type “gml:TimeInstantType”, but WFSFeatureTable's XSD parser does not support GML temporal schemas and gives up parsing the DescribeFeatureType response. Without understanding the original schema, the table falls back to guessing the field type based on the first feature. In this case, the first feature had a numeric-looking value for the field ("111"), so WFSFeatureTable guessed that it should be an integer column. When later GetFeature responses contained rows with non-numeric strings for this field, they could not be inserted into the table.
Luckily, there was a workaround. In Maps SDK 200.5+ you can implement an IHttpMessageInterceptor that listens for DescribeFeatureType responses and replaces the unsupported “gml:TimeInstantType” type with something more compatible. Here is what that implementation would look like:
class DescribeFeatureTypeRewriter : IHttpMessageInterceptor
{
public async Task<HttpResponseMessage> SendAsync(HttpMessageInvoker invoker, HttpRequestMessage message, CancellationToken cancellationToken)
{
var response = await invoker.SendAsync(message, cancellationToken);
if (message.RequestUri.Query.Contains("=DescribeFeatureType") && response.IsSuccessStatusCode)
{
// This is an XML schema returned by WFS DescribeFeatureType response.
// Edit it to replace the unsupported "gml:TimeInstantType" with "dateTime" before passing it to Runtime.
// Most of the time both are represented by ISO 8601 strings, so this is a broadly compatible change.
var xsdString = await response.Content.ReadAsStringAsync();
xsdString = xsdString.Replace("gml:TimeInstantType", "dateTime");
response.Content = new StringContent(xsdString);
}
return response;
}
}
And here is how you would hook up the interceptor on startup:
ArcGISRuntimeEnvironment.Initialize(
config => config.ConfigureHttp(
httpConfig => httpConfig.UseHttpMessageInterceptor(new DescribeFeatureTypeRewriter())
)
);