Call to simple service fails with an apparently erroneous error message - c#

When I call this service, I got this error message:
ContractDescription has zero operations; a contract must have at least
one operation
It makes no sense since my interface's function has the [OperationContract()] attribute defined.
The interface:
[ServiceContract()]
public interface ITest
{
[OperationContract()]
bool Connect(string password);
}
The SVC:
<%# ServiceHost Language="CS" Debug="true" Service="TestService.Test" CodeBehind="Test.svc.cs" %>
The svc.cs:
public class Test : ITest
{
public bool Connect(string password)
{
return true;
}
}
The call: the configuration is defined programatically because it is a library
public sealed class Validator
{
public static bool Connect(string password)
{
return ObtenirCLient().Connect(password);
}
private static LicensingService.LLMrqLicensingClient ObtenirCLient()
{
dynamic endpoint = new EndpointAddress("http://localhost/TestService/Test.svc");
LicensingService.LLMrqLicensingClient client = new LicensingService.LLMrqLicensingClient(ObtenirBinding(), endpoint);
client.Endpoint.Name = "LicHttp";
client.Endpoint.Contract = new Description.ContractDescription("TestService.ITest");
return client;
}
private static BasicHttpBinding ObtenirBinding()
{
return new BasicHttpBinding {
Name = "LicHttp",
Security = ObtenirSecurity()
};
}
private static BasicHttpSecurity ObtenirSecurity()
{
return new BasicHttpSecurity {
Mode = BasicHttpSecurityMode.TransportCredentialOnly,
Transport = ObtenirTransport()
};
}
private static HttpTransportSecurity ObtenirTransport()
{
return new HttpTransportSecurity { ClientCredentialType = HttpClientCredentialType.Windows };
}
}
If you see anything strange, please let me know!

Instead of
client.Endpoint.Contract = new Description.ContractDescription("TestService.ITest");
Try this:
client.Endpoint.Contract = ContractDescription.GetContract(typeof(ITest));

Related

WCF Proxy - Creating a generic invoke method to excute every access to the service

I'm using WCF and I made my own proxy in the client, and i want to create a method using lambda expression or Action that will excute everything.
Here is my proxy:
public class BooksProxy
{
public ChannelFactory<IBooksService> Channel { get; set; }
public BooksProxy()
{
Channel = new ChannelFactory<IBooksService>("endpoint");
}
public IBooksService CreateChannel()
{
return Channel.CreateChannel();
}
}
Here is how i use the proxy:
IBooksService proxy = BooksProxy.CreateChannel();
IList<string> lst = proxy.GetStrings();
((ICommunicationObject)proxy).Close();
I want to do something like this in the BooksProxy class:
public void Execute(Action<...> action)
{
IBooksService proxy = this.CreateChannel();
/* executing here. */
((ICummunicationObject)proxy).Close();
}
And to call it like this maybe:
IList<string> result = null;
BooksProxy.Execute(proxy => { result = proxy.GetStrings(); });
Not quite sure how to do that...
Ok, so I figured how to do it.
Here is the Proxy, The idea is to make it generic:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
}
Now here is the trick :
For void methods :
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
For return:
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
Where the TResult is the returning type.
How to use:
Proxy<IService> proxy = new Proxy();
// for a void method
Proxy.Execute(prxy => prxy.Method());
// for non void method.
var result = Proxy.Execute(prxy => prxy.Method());
So, to sum up, here is how the proxy class should look like:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
}
I recommend this solution for a custom wcf proxy without using any service reference, its really simple and easy.

Generic WCF proxy implementation

I am writing a proxy to access a WCF service where we have access to both the WCF service and the client's code.
For each method in the Service contract interface I am writing a method like this.
The trouble is that there are many methods in the interface and effectively this is turning into a copy and paste exercise.
Is there a more elegant way (with lambdas?) of doing this that isn't so verbose ? I can't quick figure it out please....
public interface IServiceContract
{
DataContracts.TypeA Method1(int arg1, string arg2);
string Method2(string arg1);
DateTime Method3();
int Method4(DataContracts.Input1);
// etc............
}
public class Proxy : IServiceContract....
public DataContracts.TypeA Method1(int arg1, string arg2)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return proxy.Method1(arg1, arg2);
}
finally
{
CloseConnection(proxy, factory);
}
}
public List<AnOtherResultPoco> Method2(string arg1)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return proxy.Method2(args1);
}
finally
{
CloseConnection(proxy, factory);
}
}
//ad inifinitum for methods,3,4,5...
If you want to factorize your code a bit using lambda, I suggest to write a method that looks like this:
...
public void ServiceCall(Action<IFileService> action)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return action(proxy);
}
finally
{
CloseConnection(proxy, factory);
}
}
So you call your service methods this way:
...
List<AnOtherResultPoco> result;
MyClass.ServiceCall(p => { result = p.Method2("hello"); });
...
You could use reflection.
public List<MyResultType> SearchBy(string searchTerm, string method)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
if (!IsMethodAllowed(method))
{
throw new SecurityException();
}
return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, new object[] { searchTerm });
}
finally
{
CloseConnection(proxy, factory);
}
}
This is another way, maybe what you are looking for.
public List<MyResultType> SearchByMethod1(int a, int b)
{
return (List<MyResultType>)SearchBy(new object[] { a, b }, "Method1");
}
public List<MyResultType2> SearchByMethod2(MyResultType b)
{
return (List<MyResultType2>)SearchBy(new object[] { b }, "Method1");
}
protected object SearchBy(object[] parameters, string method)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
if (!IsMethodAllowed(method))
{
throw new SecurityException();
}
return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, parameters);
}
finally
{
CloseConnection(proxy, factory);
}
}
This would not lead to having generics all over your code. It is neatly wrapped inside proxy.
I know its an old question, but I run into the same problem today, and found an easy solution, thought I would share for future users.
So in this solution, we will make our own proxy instead of generating a service reference.
Here is the Proxy, The idea is to make it generic:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
}
Now here is the trick :
For void methods :
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
For return:
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
Where the TResult is the returning type.
How to use:
Proxy<IService> proxy = new Proxy();
// for a void method
Proxy.Execute(prxy => prxy.Method());
// for non void method.
var result = Proxy.Execute(prxy => prxy.Method());
So, to sum up, here is how the proxy class should look like:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
}
I recommend this solution for a custom wcf proxy without using any service reference, its really simple and easy.

InstanceContextMode.PerCall acts as a InstanceContextMode.Single in wcf

I am trying to create a wcf service host with the help of code only(no config is involved).
I have a static int and InstanceContextMode.PerCall set for the wcftestservice. As per the tutorial provided on the internet, I should be having same value for every call to the wcf?
Note: I have tested this behavior in console application as well as windows service and I am testing the behavior with the help of wcf test client
Here is the code:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class WcfServiceTest : IContract
{
static int _counter;
public string GetData(string p1)
{
return Convert.ToString(_counter++);
}
}
Contract:
[ServiceContract]
public interface IContract
{
[OperationContract]
string GetData(string p1);
}
The service host code:
static ServiceHost _servicehost;
static void Main(string[] args)
{
string tcpPort = "8081";
string httpPort = "8888";
string urlWithoutProtocol = "{0}://localhost:{1}/WcfServiceTest";
string netTcpAddress = string.Format(urlWithoutProtocol, "net.tcp", tcpPort);
string httpAddress = string.Format(urlWithoutProtocol, "http", httpPort);
string netTcpMexAddress = netTcpAddress + "/mex";
string httpMexAddress = httpAddress + "/mex";
if (_servicehost != null)
{
_servicehost.Close();
}
_servicehost = new ServiceHost(typeof(wcftest.WcfServiceTest));
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
//smb.HttpGetUrl = httpUri;
//smb.HttpGetEnabled = true;
_servicehost.Description.Behaviors.Add(smb);
_servicehost.AddServiceEndpoint(typeof(wcftestcontract.IContract), new NetTcpBinding(), netTcpAddress);
Binding mexTcpBinding = MetadataExchangeBindings.CreateMexTcpBinding();
_servicehost.AddServiceEndpoint(typeof(IMetadataExchange), mexTcpBinding, netTcpMexAddress);
_servicehost.AddServiceEndpoint(typeof(wcftestcontract.IContract), new BasicHttpBinding(), httpAddress);
Binding mexHttpBinding = MetadataExchangeBindings.CreateMexHttpBinding();
_servicehost.AddServiceEndpoint(typeof(IMetadataExchange), mexHttpBinding, httpMexAddress);
_servicehost.Open();
Console.ReadKey();
}
If you want to check that it creates only once for Singleton mode, and each time for PerCall mode, then you need to increment your variable in constructor:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class WcfServiceTest : IContract
{
static int _counter;
public WcfServiceTest()
{
_counter++;
}
public string GetData(string p1)
{
return Convert.ToString(_counter);
}
}
Then for each call number will increase for PerCall, and it won't increase for Singleton mode
Yes, tutorial has a bug. In their sample should be this without static modifier:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class MyService:IMyService
{
int m_Counter = 0;
public int MyMethod()
{
m_Counter++;
return m_Counter;
}
}
Static variable means that it should be the same for all instances of object. So, for static variable there is no difference between PerCall and Signleton modes, as it will be the same.

Windows Communication Foundation Null Reference Error

I am trying to use Windows Communication Foundation(WCF) for testing purposes in my application and I am getting a null object. I am new to using WCF, so any help would be appreciated.
From what I understand, each host has one service type(class). I have several interfaces and classes I want to test. My goal is to make one master class that has instances of the others, so I don't have to have several hosts running. Below is some of my code.
Host-
public class AutomationWCFHost
{
public ServiceHost host;
public AutomationWCFHost() {
Uri httpUrl = new Uri("http://localhost:8090/MyFun");
host = new ServiceHost(typeof(MyFun), httpUrl);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
}
public void StartWCF() {
this.host.Open();
}
public void StopWCF(){
this.host.Close();
Interfaces -
[ServiceContract]
public interface IMyFun {
[OperationContract]
string Echo(string msg);
IDataSources DataSources { [OperationContract]get; [OperationContract]set; }
}
[ServiceContract]
public interface IDataSources {
[OperationContract]
void Add(DataSource dataSource);
[OperationContract]
void Remove(DataSource dataSource);
}
Class - I am trying to make one base class so I don't have to have multiple hosts running.
public class MyFun : IMyFun {
public DataSources _dataSources;
public MyFun () {
_dataSources = new DataSources();
}
public string Echo(string msg) {
return msg;
}
public IDataSources DataSources { get { return _dataSources; } set {_dataSources = (DataSources)value;} }
}
public class DataSources : IDataSources{
....//Several methods and properties
}
Test -
public void MyTest() {
EndpointAddress address = new EndpointAddress("http://localhost:8090/MyFun");
BasicHttpBinding binding = new BasicHttpBinding();
ChannelFactory<IMyFun> factory = new ChannelFactory<IMyFun>(binding, address);
IMyFun channel = factory.CreateChannel();
Assert.AreEqual("Test", channel.Echo("Test"));
IDataSources dataSources = channel.DataSources;
dataSources.Add(newDataSource);
}
As I step through, it runs the echo method fine, but when it does
IDataSources dataSources = channel.DataSources;
dataSources is null. This makes it so
dataSources.Add(newDataSource);
fails due to null exception error.

Call an operation that was dynamically added to the service contract

I have a WCF service contract (say IService1) to which I dynamically add an operation like described here.
How could I call a dynamically added operation from the client-side when all I have is an IService1 transparent proxy and the IClientChannel created via the ClientChannelFactory?
Update
I can get the RealProxy from the transparent proxy returned from the ChannelFactory using this method.
var realProxy = System.Runtime.Remoting.RemotingServices.GetRealProxy( transparentProxy );
Would it be possible to call realyProxy.Invoke(IMessage) with a fake message to trick the proxy into calling the dynamically added method?
Replace the GeneratePingMethod with this one:
private static void GenerateNewPingMethod(ServiceHost sh)
{
foreach (var endpoint in sh.Description.Endpoints)
{
ContractDescription contract = endpoint.Contract;
OperationDescription operDescr = new OperationDescription("Ping", contract);
MessageDescription inputMsg = new MessageDescription(contract.Namespace + contract.Name + "/Ping", MessageDirection.Input);
MessageDescription outputMsg = new MessageDescription(contract.Namespace + contract.Name + "/PingResponse", MessageDirection.Output);
MessagePartDescription retVal = new MessagePartDescription("PingResult", contract.Namespace);
retVal.Type = typeof(DateTime);
outputMsg.Body.WrapperName = "PingResponse";
outputMsg.Body.WrapperNamespace = contract.Namespace;
outputMsg.Body.ReturnValue = retVal;
operDescr.Messages.Add(inputMsg);
operDescr.Messages.Add(outputMsg);
operDescr.Behaviors.Add(new DataContractSerializerOperationBehavior(operDescr));
operDescr.Behaviors.Add(new PingImplementationBehavior());
contract.Operations.Add(operDescr);
}
}
and create your clients as such:
// this is your base interface
[ServiceContract]
public interface ILoginService
{
[OperationContract(Action = "http://tempuri.org/LoginService/Login", Name = "Login")]
bool Login(string userName, string password);
}
[ServiceContract]
public interface IExtendedInterface : ILoginService
{
[OperationContract(Action = "http://tempuri.org/LoginService/Ping", Name="Ping")]
DateTime Ping();
}
class Program
{
static void Main(string[] args)
{
IExtendedInterface channel = null;
EndpointAddress endPointAddr = new EndpointAddress("http://localhost/LoginService");
BasicHttpBinding binding = new BasicHttpBinding();
channel = ChannelFactory<IExtendedInterface>.CreateChannel(binding, endPointAddr);
if (channel.Login("test", "Test"))
{
Console.WriteLine("OK");
}
DateTime dt = channel.Ping();
Console.WriteLine(dt.ToString());
}
}

Categories

Resources