Wednesday, June 29, 2011

Setting file security in IIS 7.

Had some problems when migrating a web service to run on Windows 2008 R2 and IIS 7.5. Two of the asmx interfaces needed to have their own file security settings. I could not figure it out but googled it a bit and found the answer in StackOverflow:
1.In IIS7, browse to the directory containing your public.asmx and private.asmx files.
2.The title at the top will reflect the current directory, like "WebService Home". Click the "Content View" button at the bottom.
3.Right-click on your public.asmx file and choose "Switch to Features View".
4.The title should be "public.asmx Home" to confirm that you're managing the one file.
5.Add your IP restrictions. In this case, I think you want an Allow entry for 127.0.0.1 and choose "Edit Feature Settings" from the Action menu to Deny access to unspecified clients.
6.Click your containing folder again (e.g. WebService) and switch to Content View again to repeat these steps on private.asmx.

Very strange UX!?!

Wednesday, June 22, 2011

ESRI ArcGIS for Silverlight, WPF and Windows phone7 version 2.2 released

ESRI released a new version of the ArcGIS for Silverlight, WPF and WP7. Just installed the new version, one great thing is that the GraphicsLayer now has a new property GraphicsSource that makes it possible to databind the graphics into the layer. Should make some of my MVVM stuff easier to implement.

For more info see the blog post: Version 2.2 of the ArcGIS API for Silverlight, WPF, and Windows Phone is now available

Saturday, May 28, 2011

Testing ArcGIS for WPF + Funbeat + Prism.

Trying to make an Wpf Application using ArcGIS for WPF running against Funbeat API to view tracks that I made. Building the application on Microsoft Prism, made a MapModule and a PersonModule and added to two regions in the app.



A Custom Graphics Layer was made that accesses the tracks through the Funbeat APIs. The project uses MVVM Views and ViewModels to separate the GUI from the model. The Xaml files are only using databinding to show the data.

Saturday, May 14, 2011

Using NuGet to package ArcGIS WPF references.

Tested to use NuGet to create a package of the ArcGIS WPF APIs. Installed NuGet Package manager using extension manager in VS2010.



Installed the NuGet Package Explorer and created a package called ArcGIS.Client.WPF and added content, lib, framework and DLLs in the correct framework. Saved the package to a *.nupkg fil in a local folder C:\NUGet\Packages



To get make the package available to NuGet I added the folder in VS2010, Tools | Library Package Manager | Package Manager Settings





Now it's possible to use the package from a project, after starting a WpfProject in VS2010 I start up the consol by choosing, Tools | Library Package Manager | Library Package Console



when the console window opened up it's possible to choose the local folder that we added to the settings




Now it's time to install the package in the project, this is easy, only need to write install-package ArcGIS.Client.WPF and the package gets installed:



References to the package gets added to the project:



If we take look in explorer where the package ended up the filsystem looks like this:



So what's does all this mean, well you can create you own packages that can be easily be added in your projects. This makes it easier to handle dependencies and upgrades. There is a lot of packages on the NuGet Gallery but if you are missing a package or have internal DLL NuGet makes it easy to handle all external dependencies in your projects.

Friday, May 13, 2011

Ranting a bit on the changes in ArcGIS Server 10.1.

ESRI is changing the way the ArcGIS Server works in ArcGIS 10.1, See Considerations for ArcGIS Server developers: A look toward 10.1

We build a lot of SOA webservices leveraging the ArcGIS Server. These are mostly built using the pattern shown here: How to create a geocode and search Web service one of the reasons for building our web services using this pattern, was that the support for Server Object Extensions were poor and still is in ArcGIS 10. You needed to create COM enabled classes that has to be registered on the server etc, no tools, you need to write own tool (Or download SOExplorer) see: SOE Web services


To make the transition easier, I think that ESRI need to give us better tools to handle the SOE, SOAP and REST in ArcGIS Server and in ArcGIS Desktop/Engine. Also provide a solid pattern on how to build enterprise systems where the GIS systems can communicate with other business systems.

Sunday, April 03, 2011

RockPaperAzure Challenge.

Was trying to get the Bot Lab in RockPaperAzure Challenge running in Azure, But got:
Server Error
500 - Internal server error.
There is a problem with the resource you are looking for, and it cannot be displayed.


It worked ok locally but when I published the project to Azure it wouldn't run. Figured it out after a lot of trial and error, I finally found that in the Service Definition *.csdef the following lines are commented out:



  <!--<Sites> 

       <Site name="Web"> 

         <Bindings> 

           <Binding name="Endpoint1" endpointName="Endpoint1" /> 

         </Bindings> 

       </Site> 

     </Sites>-->

 




When I uncomment the lines, the project starts working in Azure. To bad that the Challenge is US only it would have been intresting to se how my bots stacks up to the competition.

Sunday, March 27, 2011

QR code generation for geo-location

Have been playing around with http://zxing.appspot.com/generator/ to generate QR code. No problem to scan in and recreate the coordinate in the phone.

Saturday, February 19, 2011

Solved: The incoming message has an unexpected message format 'Raw'.

As I mentioned in my earlier post the ArcGIS Server REST API returned "plain/text" causing the WCF client to give error message: "The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details." Found a forum post that helped solve the problem:
JSON and WebInvoke The problem can be solved using a WebContentTypeMapper created a class:

 public  class  JsonContentTypeMapper  :WebContentTypeMapper 

     {

         public  override  WebContentFormat 

                    GetMessageFormatForContentType(string  contentType)

         {

             if  (contentType == "text/plain; charset=utf-8" )

             {

                 return  WebContentFormat .Json;

             }

             else 

             {

                 return  WebContentFormat .Default;

             }

         }

     }

 




And change the app.config:

 <?xml version= "1.0 " encoding= "utf-8 " ?> 

 <configuration> 

   <system.serviceModel> 

     <client> 

       <!--<endpoint address="http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Household_Income/MapServer/4/query" 

                 binding="webHttpBinding" 

                 bindingConfiguration="ArcGISBinding" 

                 behaviorConfiguration="ArcGIS" 

                 contract="TestRestWCFClient.IArcGISApi" 

                 name="ArcGISREST" />--> 

       <endpoint address= "http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Household_Income/MapServer/4/query "

                 binding= "customBinding "

                 bindingConfiguration= "ArcGISBinding2 "

                 behaviorConfiguration= "ArcGIS "

                 contract= "TestRestWCFClient.IArcGISApi "

                 name= "ArcGISREST " /> 

     </client> 

     <bindings> 

       <webHttpBinding> 

         <binding name= "ArcGISBinding " maxReceivedMessageSize= "10000000 "/> 

       </webHttpBinding> 

       <customBinding> 

         <binding name= "ArcGISBinding2 "> 

           <webMessageEncoding webContentTypeMapperType= "TestRestWCFClient.JsonContentTypeMapper, TestRestWCFClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null " /> 

             <httpTransport manualAddressing= "true " maxReceivedMessageSize= "10000000 " /> 

           </binding> 

       </customBinding> 

     </bindings> 

     <behaviors> 

       <endpointBehaviors> 

         <behavior name= "ArcGIS "> 

           <webHttp/> 

         </behavior> 

       </endpointBehaviors> 

     </behaviors> 

   </system.serviceModel> 

   </configuration>

 

Consume ArcGIS Server REST API using WCF.

Have been trying this all day (It does not work), so I write my findings down so it can be continued another day. Found a great blog post here How to consume REST services with WCF that I tried to adapt create a client proxy against ArcGIS Server REST API. The first part creating a Operation contract an adding an endpoint to was easy to do:

 [ServiceContract ]

     public  interface  IArcGISApi 

     {

         //http://help.arcgis.com/en/arcgisserver/10.0/apis/rest/index.html 

         //http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/1/query?geometry=-125.4,35.2,-118.7,43.8&geometryType=esriGeometryEnvelope  

         [OperationContract ]

         [WebGet (

             BodyStyle = WebMessageBodyStyle .Bare,

             ResponseFormat = WebMessageFormat .Json,

             UriTemplate = "?f=json&Where={query}&returnGeometry=true&returnIdsOnly=false&outFields=*" )]

             //UriTemplate = "?method=flickr.interestingness.getList&api_key={apiKey}&extras={extras}")] 

             QueryResponse  Query(string  query);

     }

 



The app.config is configured like this:


 <?xml version= "1.0 " encoding= "utf-8 " ?> 

 <configuration> 

   <system.serviceModel> 

     <client> 

       <endpoint address= "http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Household_Income/MapServer/4/query "

                 binding= "webHttpBinding "

                 bindingConfiguration= "ArcGISBinding "

                 behaviorConfiguration= "ArcGIS "

                 contract= "TestRestWCFClient.IArcGISApi "

                 name= "ArcGISREST " /> 

     </client> 

 

 

     <bindings> 

       <webHttpBinding> 

         <binding name= "ArcGISBinding " maxReceivedMessageSize= "10000000 "/> 

       </webHttpBinding> 

     </bindings> 

 

 

 

     <behaviors> 

       <endpointBehaviors> 

         <behavior name= "ArcGIS "> 

           <webHttp/> 

         </behavior> 

       </endpointBehaviors> 

     </behaviors> 

   </system.serviceModel> 

   </configuration>

 


And the code for running sending a query looks like this:

 ChannelFactory <IArcGISApi > factory = new  ChannelFactory <IArcGISApi >("ArcGISREST" );

             var  proxy = factory.CreateChannel();

             var  response = proxy.Query(" );

             ((IDisposable )proxy).Dispose();

 


What's not working? Well seems like the response is "text/plain" (checked with fiddler) instead of "application/json". I haven't found a way to force it to be sent as "application/json". The error I get is: "The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details."


Update: To make it work read: http://mathiaswestin.blogspot.com/2011/02/solved-incoming-message-has-unexpected.html

Saturday, February 12, 2011

Zoom in to feature in ArcGIS Engine using ArcGIS Server and IFind

The second blog post on how to use ArcGIS Server from ArcGIS Engine. This post show how to zoom in on a feature using a IFind searching for a specific value on an attribute.

Basic steps include getting the layer from the map and casting the layer to the IFind interface and searching the layer for the feature. The project are expecting that the layer href="http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Household_Income/MapServer is loaded in the map.

 Private Sub FindUsingIFindToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FindUsingIFindToolStripMenuItem.Click
OnFind()
End Sub

Private Sub OnFind()
Dim state As String = "Alaska"
Dim attribute As String = "Name"
Dim layername As String = "States"
Dim control As AxMapControl = axMapControl1
Dim layer As ILayer = getLayer(layername)
Dim stateGeometry As IGeometry = Me.Find(layer, attribute, state, control.ActiveView)
control.ActiveView.Extent = stateGeometry.Envelope
control.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewAll, Nothing, Nothing)
End Sub



The code for getting the layer from the map.

 Private Function getLayer(ByVal name As String) As ILayer
Dim retLayer As ILayer = Nothing
Dim control As AxMapControl = axMapControl1
For i As Integer = 0 To control.Map.LayerCount - 1
Dim layer As ILayer = control.Map.Layer(i)
retLayer = Me.getLayer(name, layer)
If Not retLayer Is Nothing Then
Exit For
End If
Next
Return retLayer
End Function

Private Function getLayer(ByVal name As String, ByVal layer As ILayer) As ILayer
Dim retLayer As ILayer = Nothing
If TypeOf layer Is ICompositeLayer Then
Dim gLayer As ICompositeLayer = CType(layer, ICompositeLayer)
For i As Integer = 0 To gLayer.Count - 1
Dim l As ILayer = gLayer.Layer(i)
'söker rekursivt efter lagret
retLayer = Me.getLayer(name, l)
If Not retLayer Is Nothing Then
Exit For
End If
Next
Else
If layer.Name.Equals(name) Then
retLayer = layer
End If
End If
Return retLayer
End Function



The code that does the actual IFind. We cast the layer to IFind and use the Find method on the interface. Important to note is that it only work when you search for a value on an attribute, you can't do a custom query on serveral attributes.
 Private Function Find(ByVal layer As ILayer, ByVal field As String, ByVal value As String, ByVal activeView As IActiveView) As IGeometry5
Dim findLayer As IFind = CType(layer, IFind)
Dim fields As String() = {field}
'Söker med IFind efter features med attributet satt till value.
Dim array As IArray = findLayer.Find(value, True, fields, activeView.ScreenDisplay.CancelTracker)
Dim polygon As IPolygon5 = Nothing
For i As Integer = 0 To array.Count - 1
Dim featureFindData As IFeatureFindData2 = CType(array.Element(i), IFeatureFindData2)
Dim featureFields As IFields = featureFindData.Feature.Fields
Dim feature As IFeature = featureFindData.Feature
If (polygon Is Nothing) Then
polygon = CType(feature.Shape, IPolygon5)
Else
Dim topOp As ITopologicalOperator6 = CType(feature.Shape, ITopologicalOperator6)
polygon = CType(topOp.UnionEx(CType(polygon, IGeometry), True), IPolygon5)
End If
Next
Return CType(polygon, IGeometry5)
End Function



The same result as I got in the previous blog post, load the layer showing whole US:



And after running the find tool it shows Alaska:

Friday, February 11, 2011

Zoom-in to feature in ArcGIS Engine using ArcGIS Server and REST

The first blog post on how to use ArcGIS Server from ArcGIS Engine. This post show how to zoom in on a feature using a custom query.

I start by creating JSON query:

 Private Sub TestREST2ToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TestREST2ToolStripMenuItem.Click
Dim state As String = "Alaska"
'Skapar fråga för REST:
Dim requestUri As String = "http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Household_Income/MapServer/4/query"
Dim data As New StringBuilder()
data.AppendFormat("?f={0}", "json")
'case sensitive
data.AppendFormat("&Where=Name%3D'" & state & "'")
data.AppendFormat("&returnGeometry=true")
data.AppendFormat("&returnIdsOnly=false")
data.AppendFormat("&outFields=*")
ZoomTo(requestUri, data.ToString())
End Sub


Check out the service http://server.arcgisonline.com/ArcGIS/rest/services/Demographics/USA_Median_Household_Income/MapServer/4/query to find out what questions you can ask.

The ZoomTo method looks like this and loops through the result for the features returned and zoom in to the extent of the polygon returned:

 Sub ZoomTo(ByVal requestUri As String, ByVal data As String)
'Ställer REST frågan:
Dim request As HttpWebRequest = TryCast(WebRequest.Create(requestUri & data), HttpWebRequest)
'Hanterar resultat
Using response As HttpWebResponse = TryCast(request.GetResponse(), HttpWebResponse)
Dim reader As New StreamReader(response.GetResponseStream())
Dim responseString As String = reader.ReadToEnd()
Dim jss As New System.Web.Script.Serialization.JavaScriptSerializer()
jss.MaxJsonLength = 10000000
'Skulle kunna köra med datakontrakt, men då måste man skapa objektstrukturen.
'DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(object))
'Parsar resultatet för att skapa upp polygon.
Dim results As IDictionary(Of String, Object) = TryCast(jss.DeserializeObject(responseString), IDictionary(Of String, Object))
If results IsNot Nothing AndAlso results.ContainsKey("features") Then
Dim features As IEnumerable(Of Object) = TryCast(results("features"), IEnumerable(Of Object))
For Each feature As IDictionary(Of String, Object) In features
Dim geometries As IDictionary(Of String, Object) = TryCast(feature("geometry"), IDictionary(Of String, Object))
Dim polygon As Polygon = New Polygon()
Dim rings As IEnumerable(Of Object) = TryCast(geometries("rings"), IEnumerable(Of Object))
Dim i As Integer = rings.Count()
For Each ring As IEnumerable(Of Object) In rings
Dim pointCol As IPointCollection = New Ring()
For Each vertex As IEnumerable(Of Object) In ring
Dim point As IPoint = New Point()
point.X = Convert.ToDouble(vertex.ElementAt(0))
point.Y = Convert.ToDouble(vertex.ElementAt(1))
pointCol.AddPoint(point)
Next
polygon.AddPointCollection(pointCol)
Next
'Sätter om extent via polygonens
Dim control As AxMapControl = axMapControl1
control.ActiveView.Extent = TryCast(polygon, IPolygon).Envelope
control.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewAll, Nothing, Nothing)
'GetLegend()
'Dim attributes As IDictionary(Of String, Object) = TryCast(feature("attributes"), IDictionary(Of String, Object))
Next
End If
End Using
End Sub



I'm making a lot of assumptions here, that the result is a polygon, that there is only one polygon returned. But it shows the concept of getting features using REST.



The test application shows US when I start:



And zoom in on Alaska when I run the test method:


I have not done anything to boost the performance, so it feels very slow.

Wednesday, February 02, 2011

Demo ArcGIS for WP7 avklarad.

Har haft en Demo om ArcGIS for WP7.

Gjorde en Julgransinventerings App som borde vara intressant för alla som gått traskat runt i en halv meter snö strax innan jul någon gång och sökt en julgran.

Huvudsidan visar sverige och eventuellt inventerade julgranar.



Väljer man att skapa en ny julgran, så kommer man till en annan sida. Där man automatiskt får en GPS punkt och kan välja att fota Julgranen och skriva lite info.


När man sparar så kommer man tillbaka till huvudsidan. Där en ny skapade julgranen syns.

Xap packaging failed. Could not find file...

Hade en demo av Windows Phone 7 idag och fick följande fel "Xap packaging failed. Could not find file.."



Det visade sig mycket riktigt bero på att filen saknades. Berodde på att jag duktig som jag är flyttat in projekten i en underkatalog inför Demon. Lade till filen och allt fungerade som det skulle.

Tuesday, February 01, 2011

VS ger felmeddelande "Could not load file or assembly..." på 64bit maskin

Råkat ut för det här felmeddelandet några gånger nu "Could not load file or assembly..." Bloggar om detta så jag kanske kommer ihåg det tills nästa gång.

Får man felmeddelandet "Could not load file or assembly... " när man kör igång en applikation på en 64bitars maskin. Så kan det bero på att man refererar 32 bitars DLL:er i projektet. Om VS är satt på att bygga för "Any CPU" i Configuration Manager, så får man detta felmeddelande. Sätter man om projektet till att bygga "x86" istället så går det att köra projektet, detta gör man genom att lägga till "new" i solution plattform i Configuration manager.

Saturday, January 29, 2011

Demo på G: ArcGIS for WP7

Håller på och bygger en liten Demo inför en presentation som vi ska hålla nästa vecka... En kort preview:

Huvudfönstret:
Först bygger man en prototyp i (Microsoft Expression Blend) SketchFlow.


Skapa nytt objekt:


Sen "the real deal" mha ArcGIS for WP7:

Sunday, January 16, 2011

error : Whitespace is not allowed after end of Markup Extension.

Ibland får man knepiga fel som man inte direkt förstår vad dom beror på. Sitter och går igenom Hands On Labbarna för Windows Phone 7. Fick felet "error : Whitespace is not allowed after end of Markup Extension." när jag byggde projektet efter att ha suttit och matade in lite XAML kod i VS2010. Hittade felet till sist det beror på att man råkat slå in ett mellanslag i ett attribut:

 <StackPanel Orientation="Vertical" Width="{Binding Width, ElementName=View} ">  

Skall vara:

 <StackPanel Orientation="Vertical" Width="{Binding Width, ElementName=View}">