Monotouch/Wcf: How to Consume the Wcf Service Without Svcutil

Monotouch/WCF: How to consume the wcf service without svcutil

ChannelFactory<T> has a virtual method CreateChannel(). If this is not overridden, it uses dynamic code generation, which fails on MonoTouch.

The solution is to override it and provide your own compile-time implementation.

Below is an old service implementation of mine that at least used to work on MonoTouch. I split it up into 2 partial classes - the first one being linked in all builds, the 2nd only in the iOS builds (allowing the dynamic generation mechanism to still work on windows).

I've stripped it down to only contain 1 service call.

TransactionService.cs:

public partial class TransactionService : ClientBase<IConsumerService>, IConsumerService
{

public TransactionService()
{
}

public TransactionService(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}

public TransactionService(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}

public TransactionService(string endpointConfigurationName, EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}

public TransactionService(Binding binding, EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}

public AccountBalanceResponse GetAccountBalance( AccountBalanceQuery query )
{
return Channel.GetAccountBalance( query );
}
}

TransactionService.iOS.cs:
ConsumerServiceClientChannel which executes the calls via reflection)

public partial class TransactionService
{
protected override IConsumerService CreateChannel()
{
return new ConsumerServiceClientChannel(this);
}

private class ConsumerServiceClientChannel : ChannelBase<IConsumerService>, IConsumerService
{

public ConsumerServiceClientChannel(System.ServiceModel.ClientBase<IConsumerService> client) :
base(client)
{
}

// Sync version
public AccountBalanceResponse GetAccountBalance(AccountBalanceQuery query)
{
object[] _args = new object[1];
_args[0] = query;
return (AccountBalanceResponse)base.Invoke("GetAccountBalance", _args);
}

// Async version
public IAsyncResult BeginGetAccountBalance(AccountBalanceQuery query, AsyncCallback callback, object asyncState )
{
object[] _args = new object[1];
_args[0] = query;
return (IAsyncResult)base.BeginInvoke("GetAccountBalance", _args, callback, asyncState );
}


public AccountBalanceResponse EndGetAccountBalance(IAsyncResult asyncResult)
{
object[] _args = new object[0];
return (AccountBalanceResponse)base.EndInvoke("GetAccountBalance", _args, asyncResult);
}

}
}

EDIT: I just tested this with the latest MT (5.2) - it no longer needs all that extra boiler plate I had in there before, just the CreateChannel() override. I've cleaned up the sample code to match.

EDIT2: I added an async method implementation.

Which Service can allow me to pass Multiple(ComplexType) Parameters from Service to Client For Xamarin Forms?

Finally I got a solution!! I canceled my WCF Service because it has some limitation and also not work well enough with iOS. I came back to Web ApI thanks to https://stackoverflow.com/a/20226220/12448483 .Here the solution for me. It worked!! And now I pass complex and multi type parameters easily. By the way Passing parameters from client to service you need to use PostAsync, if you are confused to use it the you can check this https://carldesouza.com/httpclient-getasync-postasync-sendasync-c/

Monotouch and WCF: difference of SVCUTIL.EXE and SLSVCUTIL.EXE and how to avoid unsupported generic ChannelFactory?

WCF is a huge beast and it's very difficult to give general answers on it, too much depends on details. The general rule is that MonoTouch supports the same subset of WCF that was shipped with Silverlight (even if a few additions were made over time).

I suppose because there is no reflection available.

Reflection is available and works with MonoTouch. Reflection.Emit does not since Apple does not allow JIT'ing code on iOS devices. This can limit some API that requires code generation at runtime (but is not an issue if the code generation can be done at compile time).

... This means fixing the code generated by SVCUTIL.EXE. ...

Fighting/editing generated code is usually a bad idea (e.g. future maintenance). I suggest you try to use slsvcutil.exe before investing too much time in customizing the generated code.

... What does code look like that has to be written in that method?

The full source code for Mono's System.ServiceModel and System.ServiceModel.Web are available if you wish to provide your own channel (or customize the generated code).

Totally unclear to me: what is the difference between the two service utilities?

The SL prefix, in slsvcutil.exe, is for Silverlight. Microsoft made this tool to generate code that will only use the WCF subset available in Silverlight. Since this is the same subset supported by MonoTouch this is the best tool to use.

If I get the namespace issue sorted out, will the stubs created through the Silverlight utility make my project work, or will that also suffer from the generic channel issue?

It should work. That's how people are using (the available subset of) WCF with MonoTouch today. If there are issues with this (subset/tool) you can fill a bug report about it (with a test case) and we'll have a look at it.

Calling a WCF Service without a Service reference

Short answer yes.

As long as you have the interface, a way to connect to the service, you can create a channel and talk to service without having the reference.

The reference simply makes it easier for you to develop against.

Xamarin.Forms Connection to Wcf Service from iOS

If that would be interesting for somebody, I have resolved that issue.
As I mentioned, I didn't have a connection from my iOS device to my WCF service. And after days of searching the info, I tried to connect via physical Android device, not an emulator, and it didn't connect too!

So I investigated, that windows turned on my windows defender.... Lame mistake. After disabling that everything works perfect!

If you'll have such a mistake, please, check your connection from remote device! Hope that will help someone.

How to re-write WCF client to use ChannelFactory instead of service reference

Are you saying that the "Company Way" is to use the service helper, and that it internally creates a proxy based on ChannelFactory - or, do you want to create your own proxy class the long way. Would this work for you? An extension method on ServiceHelper would let you stay using the company way, but would not require the ServiceHelper to be changed to know about your request/response messages or anything they contain.

using CAEService;
using CAEService.MessageContracts;

public static class ServiceHelperExtensions
{
public static GetAllIncomesReponse GetIncomeRecords(this ServiceHelper, GetAllIncomesRequest request)
{
return WCFProxyHelper<ICAEServiceContract>.Use(client =>
client.GetAllIncomes(request));
}
}

Then in client code, you would replace this:

 response = client.GetIncomeRecords(item);

with this:

response = ServiceHelper.GetIncomeRecords(item);

I think you will also have to use the SVCUTIL.exe command to generate a proxy class, and then edit the result stripping out the proxy and leaving only the request/response classes and their supporting types. Alternatively, if you have already done "Add Service Reference" in VS, you can click the "Show All Files" option in solution explorer and drill into the service reference. One of those files contains the generated service proxy and its supporting types, all in one file.

MonoTouch WCF Service Reference.cs Errors

This is a bug in Mono's WSDL generation.

I created a simple test case for this, using Visual Studio 2012 Web Express, and it is working fine when copying the Reference.cs file from the Windows machine.

This is now fixed in mono/master commit aa2e9ec.

The bug affects all parameterless service methods with complex return types.

As a temporary workaround, use SlSvcUtil.exe on Windows to create the client proxy or add a dummy parameter to your service method.



Related Topics



Leave a reply



Submit