The function below is meant to convert lat, long coords to pixel
points.
When called it raises the exception:
'Server was unable to read request. --> There is an error in XML
document (2, 348). --> The specified type is abstract: name='MapView',
namespace='http://s.mappoint.net/mappoint-30/', at <view
xmlns='http://s.mappoint.net/mappoint-30/'>.'
I've played around with the SOAPRequest in the OnBeforeExecute (see
below) but nothing seems to make any difference. Am I making a mistake
in the variable declarations?
I've tried other RenderService calls but always get the same MapView
error.
function TestMapPointService(const UserName, Password: String):
boolean;
var MPS: RenderServiceSoap;
_latLong: ArrayOfLatLong;
_view: ViewByScale;
_pixelCoord: ArrayOfPixelCoord;
RIO: THTTPRIO;
begin
if not Assigned(RioHelper) then RioHelper := TRioHelper.Create;
Result := TRUE;
MPS := nil;
RIO := THTTPRIO.Create(nil);
try
RIO.OnBeforeExecute := RioHelper.OnBeforeExecute;
RIO.HTTPWebNode.UserName := UserName;
RIO.HTTPWebNode.Password := Password;
MPS := GetRenderServiceSoap(TRUE, '', RIO);
RIO := nil;
SetLength(_latLong, 1);
_latLong[0] := LatLong.Create;
_latLong[0].Longitude := -73.965; // This is Central Park
_latLong[0].Latitude := 40.784;
try
_view := ViewByScale.Create;
try
_view.MapScale := 1;
_view.CenterPoint := _latLong[0];
try
_pixelCoord := MPS.ConvertToPoint(_latLong, _view, 500,
400);
except
on E:Exception do begin
Result := FALSE;
end;
end;
finally
_view.CenterPoint := nil;
_view.Free;
end;
finally
_latLong[0].Free;
end;
finally
RIO.Free; // in case MPS didn't create
MPS := nil;
end;
end;
...
procedure TRioHelper.OnBeforeExecute(const MethodName: string; var
SOAPRequest: InvString);
begin
// SOAPRequest := SwapSubStrCI('<MapView>', '<MapView
xsi:type="ViewByHeightWidth">', SOAPRequest);
// SOAPRequest := SwapSubStrCI('<MapView>', '<MapView
xsi:type="ViewByBoundingRectangle">', SOAPRequest);
// SOAPRequest := SwapSubStrCI('<View>', '<View
xsi:type="ViewByScale">', SOAPRequest);
end;
...
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ConvertToPoint xmlns="http://s.mappoint.net/mappoint-30/">
<latLong>
<LatLong>
<Latitude>40.784</Latitude>
<Longitude>-73.965</Longitude>
</LatLong>
</latLong>
<view>
<MapScale>1</MapScale>
<CenterPoint>
<Latitude>40.784</Latitude>
<Longitude>-73.965</Longitude>
</CenterPoint>
</view>
<width>500</width>
<height>400</height>
</ConvertToPoint>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'#$D#$A
I found the soln (Brendan - microsoft.public.mappoint.webservice) so
I'm posting for any others still having the same problem.
THTTPRIO.DoBeforeExecute procedure *ignores* changes to SoapRequest
string made in OnBeforeExecute event. Rather than alter the source
I've derived a new class and overridden the procedure.
TMyHTTPRIO = class(THTTPRIO)
procedure DoBeforeExecute(const MethodName: string; Request:
TStream); override;
end;
procedure TMyHTTPRIO.DoBeforeExecute(const MethodName: string;
Request: TStream);
var
StrStrm: TStringStream;
ReqW: WideString;
begin
if Assigned(OnBeforeExecute) then
begin
StrStrm := TStringStream.Create('');
try
StrStrm.CopyFrom(Request, 0);
Request.Position := 0;
ReqW := StrStrm.DataString;
OnBeforeExecute(MethodName, ReqW);
StrStrm.Position := 0;
StrStrm.WriteString(ReqW);
Request.CopyFrom(StrStrm, 0);
Request.Position := 0;
finally
StrStrm.Free;
end;
end;
end;
procedure TRioHelper.OnBeforeExecute(const MethodName: string; var
SOAPRequest: InvString);
var req: string;
begin
if sMapViewType <> '' then begin
req := SwapSubStr('<MapView>', Format('<MapView xsi:type="%s">',
[sMapViewType]), SOAPRequest);
// ShowMessage(SOAPRequest + #13 + req);
SOAPRequest := req;
end;
end;
I'm semi-automating the <MapView> fudge by setting sMapViewType to the
ClassName of the MapView descendent variable.
e.g.
mapView := ViewByBoundingRectangle.Create;
sMapViewType := mapView.ClassName;
...
But it's still a fudge!
Presumably it's possible to alter the THTTPRIO source so that it deals
with abstract types more neatly (anyone?) but this soln at least is
working.
Hope this saves someone the hours I spent. Comments appreciated.
Darren Mossman