I am trying to use the SL xammap control with the built in openstreetmap tile source...
Everything works correctly in development but when publishing to the IIS6 server, the SL client will not display the map.
The site is configured to use SSL+128 bit encryption in IIS. If I swich this off and reload the SL app using the http:// address (instead of https:// ) it renders the map tiles correctly.
What am I doing wrong? I'm still learning on my feet here, is it an IIS setting or a web.config setting maybe?
I think you are having problems due to the cross-scheme access. Your Silverlight application was fetched using the HTTPS scheme, and you are trying to talk to OpenStreetMap using the HTTP scheme, which Silverlight is denying, I presume, due to the security violation of your more secure zone trying to talk to a less secure zone. It's possible you may be able to allow this behavior in the ClientAccessPolicy, but I suspect it doesn't let you allow calling from a secure zone to a less secure zone, only the other way around (but I could be wrong about this ;-) )
One approach would be to proxy the requests for the map tiles on your server using an HTTPS enpoint, but this would obviously increase your bandwidth burden on your server, since you would be piping the map images from OpenStreetMap.
Another approach would be to see if any of our supported tile source providers have an HTTPS service you can use rather than an HTTP service.
Yet another approach is to examine your SSL usage. Why do you need the SSL for the silverlight application? Could only the secure parts of the application elevate to SSL, or does the user need to see the HTTPS in the browser address bar? This is a common issue to address when a map is displayed in an HTTPS site, and I believe some approach it by having multiple iframes where some of the content of the page is secure and some is insecure (something most sensible browsers generate a warning about, by the way). In this way, it may be possible to host multiple silverlight applications on a page in different security zones. But you would want to investigate further along these lines.
Hope this info helps! let me know if you have any questions.
-Graham
Also, if this is for a site where you have control of the client environment (intranet). Its possible, although I'm not sure of this, that you might be able to allow this access if you add http://openstreetmap.org to the trusted sites on the client machines. But, again, I'm not sure what your outcome might be.
I believe Bing Maps (BingMapsTileSource) supports SSL, by the way.
Here's how you might proxy the requests for the tile images through a secure site you host.Before you proceed in this manner, please check to see if this is a valid usage of OpenStreetMap according to their terms of use.Also, be aware that since you are basically proxying all the OpenStreetMap image traffic for your application, that you would be increasing your site's bandwidth consumption considerably.Also note, if this is a publically accessible site, you will want to secure access to img.aspx to prevent access to the image proxy from applications other than your own.Unless you do this you may end up with other people chewing up your bandwidth!The Xaml:
<ig:XamMap Name="xamMap1" Loaded="xamMap1_Loaded" > <ig:XamMap.MapTileSource> <local:ProxiedOpenStreetMapTileSource /> </ig:XamMap.MapTileSource> </ig:XamMap>
The code behind:
public class ProxiedOpenStreetMapTileSource : MapTileSource { public ProxiedOpenStreetMapTileSource() : base(134217728, 134217728, 256, 256, 0) { } protected override void GetTileLayers( int tileLevel, int tilePositionX, int tilePositionY, IList<object> tileImageLayerSources) { int zoom = tileLevel - 8; //replace this with the appropriate url for your environment. string secureSiteRoot = "https://localhost/SilverlightApplication62.Web/"; if (zoom > 0) { string uri = String.Format( "{0}img.aspx?Z={1}&X={2}&Y={3}", secureSiteRoot, zoom, tilePositionX, tilePositionY); tileImageLayerSources.Add(new Uri(uri, UriKind.Absolute)); } } }
and the implementation of img.aspx.Please note that you would probably want to add some sort of caching/security here, etc, this is just a sketch.
public partial class img : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Response.ContentType = "image/png"; Response.BufferOutput = true; Response.Clear(); int z; int y; int x; if (int.TryParse(Request.QueryString["Z"], out z) && int.TryParse(Request.QueryString["X"], out x) && int.TryParse(Request.QueryString["Y"], out y)) { string url = "http://tile.openstreetmap.org/{Z}/{X}/{Y}.png" .Replace("{Z}", z.ToString()) .Replace("{X}", x.ToString()) .Replace("{Y}", y.ToString()); WebRequest req = WebRequest.Create(url); WebResponse resp = req.GetResponse(); resp.GetResponseStream().CopyTo(Response.OutputStream); } } }
Anyway hope that explains how one way you might approach consuming OpenStreetMap or other services from a secure Silverlight application.But there are additional concerns you would have to address before using something like this in production.-Graham
Thanks for the advice. I understand what needs to be done now.
An update for anyone experiencing similar problems....
Many thanks to Graham for his help with all of his posts.
I finally resolved this today (I've learnt a lot about cross domain policies!)
I am using SL4+RIA services to have my SL app consume various web services providing sensitive data over the web. Thus my need for SSL.
To resolve everything, I switched my SL app hosting to not requiring SSL and thus viewable over http:// . But tagged all my RIA domain service classes with
[EnableClientAccess(RequiresSecureEndpoint=true)]
This automagically tells the RIA service factory to create https:// only endpoints at runtime (the WCF services are dynamically created)
and... then as suggested by Graham, the final step for me was to then create a clientaccesspolicy.xml in my website root.
This is how mine ended up looking:
<?xml version="1.0" encoding="utf-8" ?><access-policy> <cross-domain-access> <policy> <allow-from http-request-headers="SOAPAction"> <domain uri="http://*"/> <domain uri="https://*" /> </allow-from> <grant-to> <resource include-subpaths="true" path="/"/> </grant-to> </policy> </cross-domain-access></access-policy>
This file allows you to grant access to the SL app to make calls to other domains (in my case https://mywebsite/ was being called from htpp://mywebsite/
And bingo! It all works, the service calls are secure, openstreetmaps works (and the SL app loads a little quicker - over http)
So I thought I would post my findings here in case it can be of help to anyone doing anything similar.