How to pass an object to a web service? - c#

I already searched a lot in Google.
I created a EntityClass on client side, and then I added the library reference of this class on Web Service side. But when I want to call the method, it shows this error:
Error 2 Argument 1: cannot convert
from
'Services_Library.UserService.UserServiceSoapClient'
to
'Services_Library.UserService.UserEntity'
here is the code, this method is called from a User Interface:
public UserEntity test(UserEntity userEntityx)
{
UserService.UserServiceSoapClient userService = new UserService.UserServiceSoapClient();
userService.testUserAsync(new UserEntity());
}
I think we can do this without explicit serialization, right? If so, I prefer this way.

I think the problem is when you actually call the service, you're passing in the serviceReference and not the object that the call accepts. I think it should look something like:
public UserEntity test(UserEntity userEntityX)
{
var userService = new UserService.UserServiceSoapClient();
return userService.testUser(userEntityX);
}
No explicit serialization needed.
Also, keep in mind that if you're calling the Async version of the method you're code is going to become more complicated. I used the synchronous version in my example.

Related

static class configuration for service fabric actors

Service fabric actors are used to access database and all the methods suppose to use Dapper as ORM tool.
One thing I found out as the best way to solve current problem is using something called SqlMapper in Dapper. With that, you can define general behavior in handling certain data types, for example:
SqlMapper.AddTypeHandler(new DateTimeHandler());
public class DateTimeHandler : SqlMapper.TypeHandler<DateTime>
{
public override void SetValue(IDbDataParameter parameter, DateTime dateTime)
{
parameter.Value = dateTime.ValidateDateTime();
}
public override DateTime Parse(object value)
{
return ((DateTime)value).ValidateDateTime();
}
}
As you declare static method above (AddTypeHandler) with custom handler such as DateTimeHandler, the mapping done using Dapper framework will make sure any dateTime type goes through above handler correctly.
I would like to see this happening as each Actor communicates to database via Dapper.
I haven't seen it happening yet declaring above static method in attempts with several different places such as Actor constructor() or the main method such as below:
private static void Main()
{
try
{
// This line registers an Actor Service to host your actor class with the Service Fabric runtime.
// The contents of your ServiceManifest.xml and ApplicationManifest.xml files
// are automatically populated when you build this project.
// For more information, see https://aka.ms/servicefabricactorsplatform
ActorRuntime.RegisterActorAsync<SqlRepositoryActor>(
(context, actorType) => new ActorService(context, actorType)).GetAwaiter().GetResult();
// This doesn't seem like a right place as I don't see the handler being called when Actor uses dapper mapping methods.
SqlMapper.AddTypeHandler(new DateTimeHandler());
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
throw;
}
}
I usually don't want to answer my own question, but here is what I found out so far.
First of all, maybe I need to change the title of this question if I want the actual solution solving the issue to be more relevant to the title itself. However since the titled question is answered with this post, I will keep it as is.
To give the short answer, static class configuration can be done with all the places I mentioned above such as Actor constructor, OnActivateAsync(), etc, as static class is still shared across different threads (Actors are all single independent threads) within the AppDomain (And actors are running within the AppDomain. Please correct me if I am wrong.)
What actually caused the above issue was because the mapping definition using Dapper was declared as dynamic; shown below:
return sqlConnection.Query<dynamic>(some_sql_script, new { objInstance }).FirstOrDefault();
Once you change the expected return type T to strong type which contains the typeHandler type, then Dapper invoked the typeHandler correctly:
return sqlConnection.Query<StrongType>(some_sql_script, new { objInstance }).FirstOrDefault();

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.

Reference object in two classes C#

Let's go straight to my probably fairly simple problem.
I have a LoginService class in my Services folder which makes a connection with the server. I have another UserModel where I want to receive information from the server. In order not to login again (which would be stupid), I need to maintain the client reference in both files having the same value. In other words, I need to be able to access the same object from a different class (make another reference).
I have tried and tried and searched but I am missing something.
A fairly similar post that I found that still didn't solve mine is this.
The code in my LoginService:
namespace App_Name.Services
{
class LoginService
{
public static Class_Name client;
public async Task MakeConnectionAsync(string userToken)
{
client = new Class_Name();
PasswordVault vault = new PasswordVault();
await client.LoginAsync(TokenType.User, userToken);
await client.StartAsync();
}
So now I want to get the user avatar on my UserModel.cs:
namespace App_Name.Models
{
class UserModel
{
public string GetAvatar()
{
return LoginService.client.CurrentUser.GetAvatarUrl();
}
But it always gives an exception because it tries but there is no connection.
I am sure that it was Connected because in order to load the UserModel it has to be a successful connection.
Any ideas ?
When you call directly the client.CurrentUser.GetAvatarUrl() method, its not determined by the LoginService class. You should be create the Login class before the usage. Also you are using async tasks on your LoginService class, you must confirm that already create user by your UserModel class.
For best practice you can create instance with your constructor like this.
static class LoginService
{
public static Class_Name client;
static LoginService()
{
client = new Class_Name();
}
If you want to go with static (which I not prefer for service level) not use static for like this purpose of usage.
Firstly you should be check dependency injection concepts; i suggest unity and structuremap containers. You can create your consume services by your classes without any object null ref. exception. Dependency injection decrease on coupling and null reference exception.
Ehmmm, for anyone that can use this as a reference, my code above is just fine.
The problem was with the connection API not returning the status immediately. A delay of 2 seconds solved my problem. Thanks everyone for their help.

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.

Is it possible to track all outgoing WCF call?

Our application calls external services like
//in client factory
FooServiceClient client = new FooServiceClient(binding, endpointAddress);
//in application code
client.BarMethod(); //or other methods
Is it possible to track all of these calls (e.g by events or something like that) so that the application can collect the statistics like number of call, response time, etc? Note that my application itself needs to access the values, not only to write to a log file.
What I can think is to create a subclass of VisualStudio-generated FooServiceClient and then add codes like this
override void BarMethod()
{
RaiseStart("BarMethod");
base.BarMethod();
RaiseEnd("BarMethod);
}
and the RaiseStart and RaiseEnd method will raise events that will be listened by my code.
But this seems tedious (because there are a lot of methods to override) and there is a lot of repeated codes, my code needs to change everytime the service contract changes, etc. Is there a simpler way to achieve this, for example by using reflection to create the subclass or by tapping into a built-in method in WCF, if any?
The first thing I would look at is to see if the counters available in your server's Performance Monitor can provide you with the kind of feedback you need. There's built in counters for a variety of metrics for ServiceModel Endpoints, Operations and Services. Here is some more info http://msdn.microsoft.com/en-us/library/ms735098.aspx
You could try building an implementation of IClientMessageInspector, which has a method to be called before the request is sent and when the reply is received. You can inspect the message, make logs etc in these methods.
You provide an implementation of IEndpointBehavior which applies your message inspector, and then add the endpoint behavior to your proxy client instance.
client.Endpoint.Behaviors.Add(new MyEndpointBehavior())
Check out the docs for MessageInspectors and EndpointBehaviors, there are many different ways of applying them (attributes, code, endpoint xml config), I can't remember of the top of my head which apply to which, as there also IServiceBehavior and IContractBehavior. I do know for sure that the endpoint behaviors can be added to the client proxy collection though.
I found a simple way to do it by using dynamic proxy, for example Castle's Dynamic Proxy.
Firstly, use a factory method to generate your client object
IFooClient GetClient()
{
FooClient client = new FooClient(); //or new FooClient(binding, endpointAddress); if you want
ProxyGenerator pg = new ProxyGenerator();
return pg.CreateInterfaceProxyWithTarget<IFoo>(client, new WcfCallInterceptor());
}
And define the interceptor
internal class WcfCallInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
RaiseStart(invocation.Method.Name);
invocation.Proceed();
}
finally
{
RaiseEnd(invocation.Method.Name);
}
}
//you can define your implementation for RaiseStart and RaiseEnd
}
I can also change the intercept method as I wish, for example I can add a catch block to call a different handler in case the method throw exception, etc.

Categories

Resources