Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Saturday, February 19, 2011

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

Thursday, November 19, 2009

Spara "sessionsvariabler" i WCF.

I vår loggninglösning så sparas SessionsID och Användarnamn och propageras mellan tjänster så att man kan hålla ihop anrop från en klient till underliggande tjänster. Dessa sparas som sessionsvariabler i ASP.Net och som static variabler i windows applikationer.

I ASP.Net så är det lätt att spara undan variabler i en session genom att spara i den collection som finns t.ex i Page objektet:
page.Session["SessionID"] = session.ToString();

Men i WCF är det inte lika lätt att se hur man sparar undan variabler. Detta beror till stor del på att WCF är gjort för att vara mer generellt och klara olika typer av underliggande tekniker. Man får läsa på en del innan man förstår hur det hänger ihop, här finns en bra beskrivning av InstanceContextMode:
http://msdn.microsoft.com/en-us/magazine/cc163590.aspx

Lösningen på problemet fann jag här: http://blogs.msdn.com/drnick/archive/2007/02/15/stashing-data-in-extensible-objects.aspx genom att skapa ett ExtensionObjekt som lagras på InstanceContext så uppnådde jag samma funktionalitet som tidigare i ASP.Net, dvs sessionsvariablen lever under anropets tid.

if (OperationContext.Current.InstanceContext.Extensions.Find() == null)
{
OperationContext.Current.InstanceContext.Extensions.Add(new SessionMessageInstanceContext());
}
OperationContext.Current.InstanceContext.Extensions.Find().ServiceCallCounter++;

Monday, March 16, 2009

ServiceHost directive could not be found.

Vi håller på att bygga nya tjänster med Service Factory och WCF, en kollega hade checkat in koden i TFS och när jag checkade ut koden så kunde jag inte lägga till en service referens till WCF tjänsten i mitt projekt. Testade även att köra webbläsaren mot tjänsten och fick ett fel tillbaka: "The type 'Service', provided as the Service attribute value in the ServiceHost directive could not be found." Efter många om och men hittade jag information på nätet och det visade sig att felet berodde på att sökvägen i svc filen inte kunde hitta tjänsten. Detta kunde sedan enkelt avhjälpas med att lägga in en projektreferens till implementationsprojektet.