I have a WCF Restful Service that returns JSON objects that my iPhone and Android apps consume nicely. This is my first attempt at building something like this and I left WP7 till last as my background lies with C# and VS2010. But it seems it’s not going to be a simple as I had guessed.
So I guess I have three questions:
1, Can I consume JSON objects in WP7? If so does anyone know of a tutorial?
2, if not, can I use the existing service and build some new contracts for consumption in WP7? Or,
3, do I need to build a whole new service?
Option one is most desirable but either way, I need to develop for all three operating systems so does anyone know the best type of model to bring this all together???
Cheers,
Mike.
Yes, but not with the channel factory / proxy programming model which you may be used to with WCF. REST services are usually consumed by using some simpler classes such as WebClient. You can use the JSON libraries (DataContractJsonSerializer is in the WP7 profile) then to deserialize the data you receive. Even the untyped JSON (the System.Json classes from the System.Json.dll on Silverlight), while not officially in the profile, they kind of work on WP7 as well (I've seen a few people simply referencing the SL library on a WP7 project).
If you want proxy support, you can add a new endpoint to the service using BasicHttpBinding, which is supported in WP7; if you don't need it, see 1).
No. See 1) and 2).
Try this to deserialize a JSON object:
public static T Deserialize<T>(string strData) where T : class
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
byte[] byteArray = Encoding.UTF8.GetBytes(strData);
MemoryStream memoryStream = new MemoryStream(byteArray);
T tRet = serializer.ReadObject(memoryStream) as T;
memoryStream.Dispose();
return tRet;
}
I find a totally wcf-based approach more interesting.
This is a good post that addresses this issue
http://blogs.msdn.com/b/carlosfigueira/archive/2010/04/29/consuming-rest-json-services-in-silverlight-4.aspx
Related
seems that Portable Class Library does not support PerSession (Wshttpbinding) required for this.
Is there any work around for this?
i have xamarin forms application (server client) that users can connect to their own database and get or update data.
once the user provide his username and password some information must be stored to their sessions like database connection string and when data request from user then the appropriate connection string that is stored to his session will be used for that database and send the data back.
otherwise without persession i have to pass on every function the connection string from the client.
how can i avoid this? Portable Class Library does not support wshttpbinding and therefore i cannot use PerSession
any help?
Too much Headache
The obstacles are too much for anyone working with the following combination
Xamarin Forms
PCL (Portable Class Libray)
WCF
IClientMessageInspector
The Problem:
I was need to have a multi client application that each one can connect to his own database ( same schema all )
For this purpose i was looking to store some information at a session level like (Connection String,User Information) so when a method called to know from which database i will retreive the data .
Problem # 1 ( took me 5 days to understand and realized)
that Sessions cannot be worked with PCL ( WCF PerSession) why? Because PerSession Needs WsHttpBinding but PCL Does not support WsHttpBinding only BasicHttp
Problem # 2 (took me 3 days to understand why is not working)
Then i saw many posts here and there about implementing IClientMessageInspector (see examples online how to implement IClientMessageInspector it's easy) so every time a client request a call to send some extra info to the server together with the call in my case was the connectionString. Here i was getting an exception that
NotImplementedException. Why? because of this BUG in MONO
https://bugzilla.xamarin.com/show_bug.cgi?id=40064
in simple words
When creating a WCF client in a PCL (targetting .NET Core) you must use EndpointBehaviors and not Behaviors. This works fine in a Windows RT application, but Mono has not implemented this so produces NotImplementedException in Android and iOS.
The answer is on the link above by another reply from someone else and i thank him for that .
In simple words
Instead of
MyService.Endpoint.EndpointBehaviors(New MyBehavior)
Use
Dim prop = MyService.Endpoint.GetType.GetTypeInfo.GetDeclaredProperty("Behaviors")
Dim obj = CType(prop.GetValue(MyService.Endpoint), KeyedCollection(Of Type, IEndpointBehavior))
obj.Add(New Behavior)
and instead of
clientRuntime.ClientMessageInspectors.Add(New MyInspector)
Use
Public Sub ApplyClientBehavior(endpoint As ServiceEndpoint, clientRuntime As ClientRuntime) Implements IEndpointBehavior.ApplyClientBehavior
Dim prop = clientRuntime.GetType.GetTypeInfo.GetDeclaredProperty("MessageInspectors")
Dim obj = CType(prop.GetValue(clientRuntime), ICollection(Of IClientMessageInspector))
obj.Add(New MyInspector)
End Sub
No changes needed to the configuration file
Hope this help someday someone.
I have a WCF service which transport mode is set to Streamed. The service need to accept a stream.
My Client is Compact Framework 3.5. In the client I have n list object that carries large data. I want to serialize this object to stream and send it to WCF service where I will deserialize it.
This turn out to be a mission because of the limited serialization options in Compact Framework.
Currently I have the following for the serializing:
ServiceClient sc = new ServiceClient(CommonClient.MyDefaultBinding(), CommonClient.MyEndpointAddress);
MemoryStream s = new MemoryStream();
XmlSerializer serializer = new XmlSerializer(typeof(ScannerService.AscAssetCaptureCollection));
serializer.Serialize(s, serverCollection);
OnComplete(sc.Send((Stream)s));
This is not working. The error I'm getting when trying to send is:
The type System.IO.MemoryStream was not expected. Use the XmlInclude or SoapInclude >attribute to specify types that are not known statically.
Does anyone know how can I achieve this?
There's no streaming from .NET CF. Because of memory limitations, the WCF version for .NET CF/WIN CE has a dramatically abbreviated tool set. The only option in your case for uploading files from a .NET CF device is buffering, though CF might be able to receive a stream (not sure. I've never tried it.) You're limited, too, in your binding options and encryption - SSL won't work, only message encryption.
Here's a link to the subset of features available in .NET 3.5 CF
http://blogs.msdn.com/b/andrewarnottms/archive/2007/08/21/the-wcf-subset-supported-by-netcf.aspx
Good luck ... I was able to get files uploading/downloading to CF, but it wasn't easy.
I wish to create a MonoTouch MTDialog-based app that upon launching adds a single element to the MonoTouch Dialog and then render the screen. This single element will be a JsonElement similar to this -
var je = new JsonElement ("Dynamic Data", "http://tirania.org/tmp/demo.json");
as shown in the sample application. However, instead of referencing a pre-built json file on a server, I wish to have the url point at a WCF OData service which will dynamically build the json data.
I am not sure what is the easiest way to do this. I am a bit lost after reading over the documentation. Is there some library I can include in my server-side C# app which I can then use to build out the elements and return as a json string of information?
I already have a WCF application up and running and just need to add an entry point which will call the method to create some simple json data for MonoTouch dialog to consume.
Any examples or suggestions are greatly appreciated as I am trying to get a simple solution completed by this weekend.
You're looking for a C# JSON library? How about JSON.NET http://james.newtonking.com/pages/json-net.aspx
You might also look at ServiceStack.NET -- they have a MonoTouch client.
Has anyone got a RESTful WCF service (in .NET4) successfully using JSON.NET to do serialization/deserialization?
What's the best approach?
Can you provide a few more details about what you're trying to do with JSON.NET? I'm not exactly sure what scenarios you're trying to deal with -- but I'll give you my general experience with JSON.NET and WCF RESTful services.
I've built a number of WCF RESTful services that are called, primarily, by my client app using jQuery's AJAX functionality. Generally, I have not had to use JSON.NET as the JsonSerializer does a fine job of serializing my return values (single values or List<T> collections) perfectly fine and can navigate through the object without issue.
The times that I've had to use JSON.NET is when I'm sending a JSON object as part of my POST variables that I've serialized on the client using the JSON2.js library. JSON.NET has done a fine job of serializing and deserializing those values without issue, too.
I like JSON.NET -- haven't had any issues. Honestly, when I started out, I thought I would use it a lot, but have found that I only need it for edge cases. Generally I rely on the built-in JSON serialization and deserialization capabilities in WCF.
I hope this helps. Please let me know if you need more info or if there are specific scenarios you're trying to handle, and I'll update my answer accordingly. Thanks!
Just wondering under what circumstances would you prefer to generate a proxy from a WCF service when you can just invoke calls using the ChannelFactory?
This way you won't have to generate a proxy and worry about regenerating a proxy when the server is updated?
Thanks
There are 3 basic ways to create a WCF client:
Let Visual Studio generate your proxy. This auto generates code that connects to the service by reading the WSDL. If the service changes for any reason you have to regenerate it. The big advantage of this is that it is easy to set up - VS has a wizard and it's all automatic. The disadvantage is that you're relying on VS to do all the hard work for you, and so you lose control.
Use ChannelFactory with a known interface. This relies on you having local interfaces that describe the service (the service contract). The big advantage is that can manage change much more easily - you still have to recompile and fix changes, but now you're not regenerating code, you're referencing the new interfaces. Commonly this is used when you control both server and client as both can be much more easily mocked for unit testing. However the interfaces can be written for any service, even REST ones - take a look at this Twitter API.
Write your own proxy - this is fairly easy to do, especially for REST services, using the HttpClient or WebClient. This gives you the most fine grain control, but at the cost of lots of service API being in strings. For instance: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content; - if the details of the API change you won't encounter an error until runtime.
Personally I've never liked option 1 - relying on the auto generated code is messy and loses too much control. Plus it often creates serialisation issues - I end up with two identical classes (one in the server code, one auto generated) which can be tided up but is a pain.
Option 2 should be perfect, but Channels are a little too limiting - for instance they completely lose the content of HTTP errors. That said having interfaces that describe the service is much easier to code with and maintain.
I use ChannelFactory along with MetadataResolver.Resolve method. Client configuration is a bother, so I get my ServiceEndpoint from the server.
When you use ChannelFactory(Of T), T is either the original contract that you can get from a reference in you project or a generated contract instance. In some projects, I generated the code from a Service Reference because I could not add a reference to the contract dll. You can even generate an asynch contract with the service reference and use that contract interface with ChannelFactory.
The main point of using ChannelFactory for me was to get rid of the WCF client config information. In the sample code below, you can see how to achieve a WCF client without config.
Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()
In my final project, the availableBindings are checked to use net.tcp or net.pipe if available. That way, I can use the best available binding for my needs. I only rely on the fact that a metadata endpoint exist on the server.
I hope this helps
BTW, this is done using .NET 3.5. However it does work also with 4.0.
Well in order to use ChannelFactory<T> you must be willing to share contract assemblies between the service and the client. If this is okay with you then ChannelFactory<T> can save you some time.
The proxy will build async functions for which is kind of nice.
My answer is a kind of summary of Keith's and Andrew Hare's answers.
If you do not control server, but have only WSDL/URL- generate proxy using Visual Studio or svcutil. (Note that Visual Studio sometimes failed, when svcutil works better).
When you control both server and client, share interfaces/contracts and call ChannelFactory
.
It's not just a matter of time saved. Using the WSDL generated proxy is dangerous because if you forget to update the service reference you can leave the solution in an inconsistent state. Everything compiles but the service contract is broken. I definetly suggest to use a ChannelFactory whenever possible, you make your life much easier.
A possible alternative could be to write a prebuild script that calls the SVCUtil utility to create the proxy everytime you build your project, but anyway ChannelFactory is much more neat and elegant.