Create Asynchronous client to consume WCF created with SVCutil.exe - c#

I have my WCF which only returns a Boolean, has the contract created and within the WCF tests everything works correctly. The problem arises when I create the client and it does not execute the methods asynchronously.
I need to know if there is a way for the methods to run asynchronously.
Is there a way to generate an asynchronous method with the SVCUtil that works?
This is my interface
[ServiceContract]
public interface IService1
{
[OperationContractAttribute]
bool booleanMethod ();
}
TestWCF.svc class
public class TestWCF: IService1
{
public bool BooleanMethod ()
{
return BooleanMethod();
}
}
After this I generate my class with the svcUtil statement in the Developer Command Prompt.
svcutil.exe http://MyTest//Service.svc?wsdl
The created file is placed in my Xamarin Project and it works correctly when I use my normal method, but when using the same method asynchronously it gives me an error.
bool Result = Test.BooleanMethod (); // Execute correct
bool ResultAsync = Test.BooleanMethodAsync (); // It does not execute correctly
Can someone help me with the client's asynchronous calls?

Related

Global.asax.cs Application_BeginRequest - Throw WebFaultException

Is there a way in WCF to check some logic based on the type of Request it receives? Can this be done in the actual service endpoint code?
For example:
After Service Initialization my service receives a PUT Request. In myService.svc.cs I would like to have logic that looks like this:
if httpRequest.Type == PUT
{
//Do Something
}
Is this possible? I'm sure there is a better way to handle requests than adding logic for every Operation Contract that is of type PUT. Apologies if this question doesn't make sense I'm sort of new to WCF and am trying to learn. Please let me know if you need clarifiers.
EDIT:
This is what myService.svc.cs looks like currently:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public partial class MyService: IMyService
{
public async Task<someObject> GetMethod1 () // Some GET Method
{
doSomethingForGetRequests();
//method implementation
}
public async Task<someObject> GetMethod2 () // Some GET Method
{
doSomethingForGetRequests();
//method implementation
}
public async Task<someObject> PutMethod1 () // Some PUTMethod
{
doSomethingForPutRequests();
//method implementation
}
doSomethingForPutRequests()
{
if(config.IsReadOnly)
{
throw new WebFaultException(HttpStatusCode.BadRequest);
}
}
}
I am wondering if there is a place where i can place doSomethingForGetRequest() and doSomethingForPutRequest() in a central location before the request reaches these methods so I don't have to add these methods to each one of my Service Methods.
Would global.asax.cs Application_BeginRequest() be an appropriate place for this logic?
Maybe a message inspector can help you, it's called on every request that arrives at the service.
IDispatchMessageInspector defines the methods that enable custom inspection or modification of inbound and outbound application messages in service applications.
You can check out these posts:
Detect if action is a POST or GET method
Call the method automatically for each and every request in the WCF REST

Error in Web Service ASMX in XAMARIN

I have a problem when calling a web-service(asmx) in Xamarin.forms. My web-service works in Android and I generated it with svcutil.exe, but when I tested it in IOS I got a problem saying:
"Mono touch does not support dynamic proxy code generation"
After searching I found out that I have to use a Silverlight tool called SLSvcutil.exe in order to override the CreateChannel method, and to make it work in IOS. It worked, but I need the methods to be synchronous (not async).
I kept searching how to make a pure synchronous method for my web-service and I found this: Monotouch/WCF: How to consume the wcf service without svcutil
Here is my code:
protected override POService2Soap CreateChannel()
{
return new POService2SoapClientChannel(this);
}
private class POService2SoapClientChannel : ChannelBase<POService2Soap>, POService2Soap
{
public POService2SoapClientChannel(System.ServiceModel.ClientBase<POService2Soap> client) :
base(client)
{
}
public ClientLoginResponse ClientLogin(ClientLoginRequest request)
{
object[] _args = new object[1];
_args[0] = request)
return (ClientLoginResponse)base.Invoke("ClientLogin", _args);
}
I get the interface from the Silverlight-generated code, and I create the LoginResponse class there etc, but the problem comes where i call base.invoke("Client Login",_args).
Basically, the ChannelBase doesn't have an Invoke method, it only has BeginInvoke and EndInvoke. So I get the problem cause there is no Invoke in the ChannelBase class inside ClientBase. How can I invoke this, or does anyone have any better solution for getting synchronous results from the web-service?
P.S. I know why Silverlight has async methods, also I know that it is better to async now, and I also know that web-services (asmx) especially in mobile development are a bit "outdated". But in my case I need it like that.
Thanks in advance.

WCF invoke not interfaced method?

just came across a problem.
I'm trying to make a wcf service unittest ready or better all code have to be tested with unittest.
Atm its not possible coze I've got a connection to a crm 2011 server that is used every time.
so i replaced it with a Interface. but i want to unittest the WCF like you use it.
now my idea is to make a public method and and give a fake connection.
now my question is would it be possible to invoke this method(example: ConnectionHandler), even if its not in the interface?
this would look like this:
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
public class WCF: IWCF
{
public bool method1(){
...
}
public bool method2(){
...
}
private connection connectionHandler;
public connection ConnectionHandler(Iconnection con){
if(con != null){
connectionHandler = con;
} else {
connectionHandler = takedefault;
}
}
}
Edit
ah i forgot to tell this: im actually have the security in mind, i don't want that anyone can pass a different connection to the server its for unittest purpose only.
It is possible to invoke this method, you can cast the interface to the concrete object. But that would compromise the calling code, which should not know the implementation details of your service.
I would reccomend in your sittuation to use the constrcutor injection so your service implemetation would look like this:
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
public class WCF: IWCF
{
private connection connectionHandler;
public WCF(Iconnection con)
{
if(con != null){
connectionHandler = con;
} else {
connectionHandler = takedefault;
}
}
public bool method1(){
...
}
public bool method2(){
...
}
}
In this case the client code will not know the details of the service implementation, if you use the constrcutor injection on the client as well
One of important features of any well designed piece of code is that you are explicit about the functionality that you expose to your clients. This becomes a key feature of service orientated applications, as you are exposing your functionality in a standardised way for external clients to consume.
Calling a method that is not part of the interface is bad in principle as you are now programming to the implementation and not the interface. Happily WCF knows this and will not let you a method that is not on the interface as it is not decorated with the OperationContract attribute.
With respect to your code - I am not sure exactly what it is you are trying to achieve - to have a client set (what I assume is) something like a database connection makes me a little uneasy (for a start this means your service is holding some state which goes against the Service statelessness principle). This does not mean that what you are doing is necessarily wrong, but you should find that you only rarely have to violate this in a well designed application.
That said, if you want to expose different areas of functionality to different clients the correct way to do this is by exposing endpoints on your service representing the different contracts:
[ServiceContract]
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
[ServiceContract]
public interface IConnectionWCF
{
[OperationContract]
bool SetConnection(string connection);
}
public class WCF : IWCF, IConnectionWCF
{
public bool method1()
{
...
}
public bool method2()
{
...
}
public bool SetConnection(string connection)
{
...
}
}
You also need to be mindful that everything the WCF service received must first be serialized by the client, sent over the wire, and deserialized on the server. You are very much dealing with concrete classes here - not abstractions. Passing an interface (such as Iconnection) as an argument to a service call does not really make any sense in a service-orientated environment.
With regards to unit testing - just remember that fundamentally the class WCF is just a plain old class. You can unit test this class in isolation of the fact that it is a WCF service. You shouldn't be setting up any of the service hosting functionality within your unit tests anyway - you want to check that the code that YOU write is correct - the WCF stack has already been tested by Microsoft.
EDIT
In response to your comment, as suggested here, you should used constructor injection to set the connection object when the class is instantiated. This then raises the question of how you gain control over the instantiation of the WCF service. You need to implement IInstanceProvider, or for a more detailed implementation see here. This way, when you service is hosted in WCF, you use IInstanceProvider, when you are testing you simply pass your fake connection object to the constructor.
EDIT
To clarify, a unit test for this class would resemble this:
[TestClass]
public class UnitTests
{
[TestMethod]
public void Test()
{
Iconnection connection = new FakeConnection();
WCF classUnderTest = new WCF(connection);
//Run test logic
}
}

WCF method parameter order

In my WCF web service, I have the following interface:
[ServiceContract]
public interface ITestService
{
[OperationContract]
void TestMethod(out int param1, out int param2);
}
When I add the service reference in the client side, the generated client method does not match correctly the original signature, it maps one of the out parameter as the method return. I have to call it this way:
using (var client = new TestServiceClient())
{
int param2;
int param1 = client.TestMethod(out param2);
}
Is there any way I can "force" the proxy to be generated being faithful to the original method signatures?
I'd consider to change your service to return data structure with 2 properties, and return it from your operation, instead of using out parameters.
I believe this is a limitation of the proxy generation code. You'd have to edit the generated proxy code in the client in order to change this.
Technically it IS being faithful. If you dig into the Reference.cs, you will see that when the proxy calls your service, the call is the same. However, the proxy or "wrapper" that calls the service decided to "wrap" your service call differently.
The only way to make the proxy itself keep the same signature is to write it yourself. This is EXACTLY the same issue people have when reflecting a DLL. Sure you can reflect it and get the "source code", but the reflected code will be different than the original source, although the functionality will be the same.

difference in consume WCF service - Console vs Silverlight

Can someone tell my why when I have wcf contract:
[ServiceContract]
public interface IService1
{
[OperationContract]
string TestGetName();
}
and implementation
public string TestGetName()
{
return "Kasia";
}
When I try consume it in Console app I can do just that:
Service1Client client = new Service1Client();
Console.WriteLine((client.TestGetName()));
but in Silverlight I must use that way :
Service1Client clientTest = new Service1Client();
clientTest.TestGetNameCompleted += new EventHandler<TestGetNameCompletedEventArgs>(clientTest_TestGetNameCompleted);
clientTest.TestGetNameAsync();
void clientTest_TestGetNameCompleted(object sender, TestGetNameCompletedEventArgs e)
{
this.dataGridChild.DataContext = e.Result;
}
Why in SL I don't see this first short solution, but only this with Event handlers?
Or better... why in Console app I can choose synchro operation generation and in SL I must use Generate asynchronous operations... :/
A synchronous call would stop the Silverlight UI thread and possibly the executing environment, i.e. the browser. To prevent this, only asynchronous calls are allowed.
Of course this is something unusual at first, but in the long run it is actually helpful to decouple the view and service layer.
Silverlight does not support synchronous calls (which is what you're doing in your console app).
Update: http://forums.silverlight.net/forums/p/34531/104526.aspx "The main point is that it looks like synchronous behaviour was removed on account of not being supported by all browsers."

Categories

Resources