Not able to reference Operation contract method in WCF - c#

I am creating a basic Add 2 numbers service in WCF. I have added the following inside IService.cs
[ServiceContract]
public interface ICalc{
[OperationContract]
int Add(int a, int b);
}
Now, inside the Service.cs I have added
public class Service: IService, ICalc {
public int Add(int a, int b){
return a+b;
}
}
Now I build this service and add a service reference to it inside a console application
Program.cs
It is called as
ICalService.Service c = new ICalService.Service();
int result = c.Add(10,20); //Now on this line I cannot seem to get the Add(int a, int b) method
which I had declared earlier.
ICalService
is the name I gave to my service when it was referenced.
Why does the Add(int a, int b) method not show up?

Did you create a proxy for your IService interface or ICalc interface? From what it looks like you must have created a proxy for IService interface.
While adding web reference in the console application, ensure that you are creating a proxy (adding reference) to ICalcService interface.

Maybe it is just a typo or missing from your question, but I don't see the interface IService actually defined, it is only implemented on your class 'Service'. Also, it is sometimes helpful to simply browse to the .svc page you are trying to reference, the browser will sometimes show better error messages than what you would receive by trying to execute the action.
EDIT:
I would ensure that you're able to browse the .svc page and generate a WSDL. If you're able to view the service operation and get a generated wsdl than I believe your service is up and running fine. I would take others suggestion and ensure that you are then creating the proper proxy object.

Related

Wcf referenced Class code update

I am new to wpf and wcf C# application development and stuck into updating the class where wcf service is referenced. For example, Service has a class of testDbConnect and has various service operation contracts functions defined and implemented in iservice.cs and service.cs. Then in wpf class , this service is added as a reference and works perfect when calls the service functions by button click operation. Like this is what I am testing on button click.
Service1Client service = new Service1Client();
if (service.Testdb() == 1) //Testdb is the function in service which is only returning 1
{
MessageBox.Show("Hello there");
}
The problem I am facing, It perfectly starts service and show the message box( hello there) on button click but when I am updating the code even inside the button click , it still keep showing the hello there message box and not updating code. Maybe there is some proxy generation included but I am not understanding it. It'll be great If someone could explain me in easy words and tell me how It could be solved. Thanks
Based on the way you're consuming your WCF Service you need to update your services references.
Suppose you need to rename int Testdb(); in your service for int TestDb();. You go to your contract (IService1.cs), change the signature to match:
IService1.cs
[ServiceContract]
public interface IService1
{
[OperationContract]
int TestDb();
}
Then go to your service and update your method:
Service1.cs
public class Service1 : IService1
{
public int TestDb()
{
return 1;
}
}
Then, on the server side your good to go, but you need to update your service reference on your client app, so your proxies reflect the new method signature. So in your client app you expand Service References folder, right-click ServiceReference1 - or the name of your service reference - node and select Update Service Reference.
Let Visual Studio update the service reference and then you should be able to call the TestDb method by the new name.
Hope this helps!

Find all references with WCF OperationContract and DataContracts

I'm trying to figure out if there's a way to "Find all references" (using the VS feature, as opposed to Control+F entire solution). when it comes to WCF Data and OperationContracts. In case that is unclear:
namespace WcfTestReferences
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello world");
DoStuff();
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
var results = client.GetData(42);
Console.WriteLine(results);
}
static void DoStuff() { }
}
}
namespace WcfTestReferences.WCFApp
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
}
Solution looks like this:
Now, if I look at DoStuff() with code lens, I can see that it in fact has a reference to it:
But the same does not hold true for the methods being called in the wcf service:
In the above, the only references to the interface/method is the interface/method. I understand that the reference that I was hoping would be there (from the main method):
var results = client.GetData(42);
is not there, because the client is generated, and is not actually my Service1 implementation... but is there a way to change this?
In the real world, we have a WCF layer with thousands of methods, many of which are not used - but I cannot rely on Code Lens/Find all references to make this determination. Is there any way to change this behavior?
because the client is generated, and is not actually my Service1
implementation
This is the root of the problem.
You are correct - there is no way for your code analyser to determine that the GetData() call you are making from your client is semantically the same thing as the GetDate() service operation you have defined on your interface, because from a binary perspective they are defined in two completely different types.
The root of this is that you're using a service reference. WCF provides service references as the default way of connecting to a service, but in my opinion service references are problematic and should be avoided.
Luckily, WCF provides another way of consuming and calling a service via the user of ChannelFactory<T>. One of the many benefits you will get when using this instead of a service reference is that your client will have use of the service interface via a binary reference to the assembly containing your service definition.
This will allow tools like code lens to resolve references to your interface methods directly to your consuming clients.

Is changing a parameter in a OperationContract to it's Nullable<T> equivalent considered a breaking change?

Consider the following ServiceContract-Interface:
[ServiceContract]
public interface ITest
{
[OperationContract]
void MyMethod(int a, int b);
}
Now we change it to the following (effectively changing parameter int a to a int? a):
[ServiceContract]
public interface ITest
{
[OperationContract]
void MyMethod(int? a, int b);
}
Would a client consuming this WCF-Service need to make additional changes to work with the new service definition?
I finally had time to test everything and figured out my own answer.
It is not a breaking change for the following frameworks:
.NET (C#, 4.5)
Java 8
I did not test anything else as it doesn't matter for our scenario.
This means every client still works (without regenerating the client) even after updating the web service definition

Using ASMX Web Service Entities in WCF Service

We have a good old .asmx web service (let's call it "Message" Web Service) which we have to preserve for backward compatibility.
The .asmx service exposes this method:
[WebMethod(Description = "Do Something")]
public int DoSomething(Entity1 e)
{
...
}
This web service uses some entities referenced from a DLL, for example:
namespace Software.Project.Entities
{
[DataContract]
public class Entity1
{
[DataMember]
public string property1{ get; set; }
// Lots of other properties...
}
}
This DLL is also used by a brand-new WCF service. Now, I have to call the old .asmx method from WCF. To do so, in the WCF project, I added a reference to the .asmx project, using the "Add service reference" wizard (Advanced - Add Web Reference).
Now, great! It is possible for me to call the DoSomething method from WCF, this way:
Entity1 e1 = new Entity1();
Software.Project.WCFService.ServiceReferenceName.Message m = new Software.Project.WCFService.ServiceReferenceName.Message();
m.Url = ConfigurationManager.AppSettings["MessageWebServiceURL"];
int r = m.DoSomething(e1);
Unfortunately, doing so won't work: I get a compiler error like if Entity1 in WCF is not good as argument for method DoSomething. What I have to do is:
Entity1 e2 = new Software.Project.WCFService.ServiceReferenceName.Entity1();
Software.Project.WCFService.ServiceReferenceName.Message m = new Software.Project.WCFService.ServiceReferenceName.Message();
m.Url = ConfigurationManager.AppSettings["MessageWebServiceURL"];
int r = m.DoSomething(e2);
By doing so, the compiler accepts the call; the problem is that Entity1 in my WCF service is full of fields and data and I would have to copy all the data to the new entity.
I also tried adding the reference to the .asmx as a Service Reference, and flagging "Reuse types in reference assembly", but the result was exactly the same.
I can't believe that there isn't a way to make it understand that Entity1 is exactly the same entity! Is that really impossible?
I am sorry, but i think I have bad news.
You can try to use xml serialization instead of data contract serialization, since asmx does not know about it.
Also, this post say this possible but not so easy: .NET 3.5 ASMX Web Service - Invoked via .NET 3.5 Service Reference - Common Class Reuse
Probably you'll find easier to add your translator class.

Is it possible to use generic DataContract's from the client end?

I know when you create a service you can create a generic DataContract:
[DataContract(Name = "Get{0}Request")
public sealed class GetItemRequest<T>
where T : class, new() { ... }
[DataContract(Name = "Get{0}Response")
public sealed class GetItemResponse<T>
where T : class, new() { ... }
[ServiceContract]
public void MyService : IMyService
{
[OperationContract]
GetItemResponse<Foo> GetItem(GetItemRequest<Foo> request);
}
This generates a GetFooRequest and GetFooResponse definition for my WSDL. Now, what I'm curious about is if it is possible to go in the other direction?
Is it possible to create a client that uses the Generic DataContracts and pass those to the server as a concrete object? I attempted this after adding a Service Reference and it didn't really work out so well. So this is more of me wondering if there is any way (even if it means not adding a Service Reference) to do this?
Ultimately, WCF is going to look at the contract class. If that is generated from WSDL/MEX it won't have this (since this isn't how it is expressed in the metadata) - but if your client has the code as above, then sure it should work fine.
If you add a library reference (i.e. a dll / project reference) to your DTO dll from the client, and ensure WCF has shared-assemblies enabled, it should work. If it still baulks, then cheat: use a service reference just to get the config data. Then delete the service reference but keep the configuration (those config files are a pain otherwise). Then it should locate the type from the library.

Categories