Not able to call a wcf service from client - wcf

Getting an error "System.InvalidOperationException: 'Attempted to get contract type for ITC2DataService,
but that type is not a ServiceContract, nor does it inherit a ServiceContract.".
Note : I have already decorated the interface "ITC2DataService" with "ServiceContract" attribute. But still error occurs.

In addition to adding ServiceContract to ITC2DataService, the service class also inherits derived contracts, such as the following :
public class Service1 : ITC2DataService
{
...
}
The corresponding endpoint binding in the Web.config file needs to specify the correct contract (like the endpoint address "ws" below).
<services>
<service name="WcfService.Service1" behaviorConfiguration="WcfService.Service1Behavior">
<!-- ITestCallback needs to be the contract specified -->
<endpoint address="ws" binding="wsHttpBinding" contract="WcfService.ITestCallback">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>

Related

WCF service hangs when calling method, however method is working

Hello I'm having issue with my wcf service. I'm trying to call method which returns list of type object. I'm also using entity framework.
public IList<Product> GetAllProducts()
{
using (var db = new AuctionContext())
{
return db.Products.ToList();
}
}
</service>
<service name="AuctionSystem.WcfService.ProductService">
<endpoint address="" binding="wsDualHttpBinding" contract="AuctionSystem.WcfService.Contracts.IProductService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9993/Design_Time_Addresses/AuctionSystem.WcfService/ProductService/" />
</baseAddresses>
</host>
</service>
And contract :
[OperationContract]
IList<Product> GetAllProducts();
The method itself is working, but when I try to invoke this method on my wcf service UI it got stuck at "invoking service" I'm using wsdualhttpbinding.
Any ideas please?
EDIT: I realized in Product object I have virtual List, why is this List causing wcf to hang?
For all wondering why It was caused because of circular dependency.

HTTP Error 404.0 - Not Found when trying to access wcf locally

I'm getting this
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
when trying to access the service from my browser. Here is my config.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!-- Note: the service name must match the configuration name for the service implementation. -->
<service name="WcfServiceLibrary.Service1" behaviorConfiguration="MyServiceTypeBehaviors" >
<!-- Add the following endpoint. -->
<!-- Note: your service must have an http base address to add this endpoint. -->
<endpoint contract="WcfServiceLibrary.Service1" binding="basicHttpBinding" address="http://localhost/service1" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="http://localhost/service1/mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- Add the following element to your service behavior configuration. -->
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost/service1" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
When I type http://localhost/service1 in the web browser I get the 404. But if I remove the app.config below and just simpley do this in the code behind
string serviceUrl = "http://localhost/service1";
Uri uri = new Uri(serviceUrl);
host = new ServiceHost(typeof(Service1), uri);
host.Open();
All works well... Any ideas? Seems simple enough.
I think you are missing the host element under your services:
<service name="WcfServiceLibrary2.Service1">
<host>
<baseAddresses>
<add baseAddress = "http://localhost/service1" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary2.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
Service host does not need URL then.
static void Main(string[] args)
{
var host = new ServiceHost(typeof(Service1));
host.Open();
Console.WriteLine("Host running");
Console.ReadLine();
}
You can show http://localhost/service1?Wsdl in the browser but mex only works with add service reference or WCFTestClient (C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE) because you will get the HTTP Bad Request error which comes from the fact that the browser issues an HTTP GET request where the contents of the message are in the HTTP headers, and the body is empty.
This is exactly what the WCF mexHttpBinding is complaining about.

Generic Service Interface

I have a Generic Service Interface:
[ServiceContract]
public interface IService<T> where T : Class1
{
[OperationContract]
void DoWork(T class1);
}
Then I have a Concrete Service that inherits from that:
public class Service : IService<Class1>
{
public void DoWork(Class1 class1)
{
}
}
Everything works fine until I add a webHttpEndpoint to expose a JSON WS:
<service name="Service">
<endpoint
address=""
binding="webHttpBinding"
behaviorConfiguration="webHttpBehavior"
contract="IService" />
</service>
<behavior name="webHttpBehavior">
<enableWebScript />
</behavior>
In fact, I receive this error:
The contract name 'IService' could not
be found in the list of contracts
implemented by the service 'Service'.
That's beacuse of the generic definition of the interface.
Any solution?
In my opinion (and based on what you said), the interface does not need to be generic. The caller just need to know that there is a DoWork operation.
So basically, change the concrete class to be generic instead of the interface.
public class Service<T> : IService where T : Class1
{
public void DoWork()
{
}
}
EDIT after clarifying the question: You need to provide the generic parameter in the config file as well:
contract="YourAssembly.IService`1[[YourAssembly.Class1, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"
Here is a similar question: Inheriting from a generic contract in WCF
You must correctly write the type name of your contract into configuration. IService is not the name of IService<Class1>!!!
The configuration should look like:
<service name="Service">
<endpoint
address=""
binding="webHttpBinding"
behaviorConfiguration="webHttpBehavior"
contract="IService`1[Class1]" />
</service>
<behavior name="webHttpBehavior">
<enableWebScript />
</behavior>
Be aware that if your contract or service lives in any namespace, namespaces should be included in configuration.
Or in case of full names needed:
<service name="Namespace.Service, AssemblyName">
<endpoint
address=""
binding="webHttpBinding"
behaviorConfiguration="webHttpBehavior"
contract="Namespace.IService`1[[Namespace.Class1, AssemblyName]], AssemblyName" />
</service>
<behavior name="webHttpBehavior">
<enableWebScript />
</behavior>
Where is your Class1.....Instead of specifying any specific class make it a reference type using class
Try something this...
[ServiceContract]public interface IService<T> where T : class
{
[OperationContract]
void DoWork();
}

How use injection in wcf

I have two classes implementing a contract at a service which are consumed from a factory on the client like shown below.
[ServiceContract]
public interface MyInterface {
void DoSomething()
}
public class A : MyInterface {
public void DoSomething(){
"Hi I'm A"
}
}
public class B : MyInterface {
public void DoSomething(){
"Hi I'm B"
}
}
public class MyFactory <TMyInterface> {
void DoSomething(){
TMyInterface.DoSomething()
}
}
The client must remain the same. My question is how can I choose at the server side which implementation of MyInterface to use, by passing the type parameter using .config file in WCF
I read other post but I don't understand yet :(
It is possible to do it, and there are a few ways to do it.
One possibility is to create a "routing" service which will contain the "public" address which the client always talks to. This routing service can then, based on some configuration, redirect the call to the appropriate "real" service.
Another way is to actually have a process which starts both services, but their addresses are defined in config. If you use the same binding and the same contract (which is the case), then you can "flip-flop" the service address when you want to change the service which will receive the calls from the client. For example, this configuration directs the requests to the endpoint at "http://machine-name:8000/Service" to service A. Notice that, since you define service hosts for both services, you actually need to have a base address for service B as well - in this case I used named pipes, which cannot be accessed via different machines.
<system.serviceModel>
<services>
<service name="A">
<host>
<baseAddresses>
<add baseAddress="http://machine-name:8000/Service"/>
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding" contract="MyInterface" />
</service>
<service name="B">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/ServiceBackup"/>
</baseAddresses>
</host>
<endpoint address="" binding="netNamedPipeBinding" contract="MyInterface" />
</service>
</services>
</system.serviceModel>
when you want to change the address for B, you'd then swap the addresses.
<system.serviceModel>
<services>
<service name="A">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/ServiceBackup"/>
</baseAddresses>
</host>
<endpoint address="" binding="netNamedPipeBinding" contract="MyInterface" />
</service>
<service name="B">
<host>
<baseAddresses>
<add baseAddress="http://machine-name:8000/Service"/>
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding" contract="MyInterface" />
</service>
</services>
</system.serviceModel>
The hosting program would look like this:
public static void HostServices()
{
ServiceHost hostA = new ServiceHost(typeof(A));
ServiceHost hostB = new ServiceHost(typeof(B));
hostA.Open();
hostB.Open();
Console.WriteLine("Press ENTER to close");
Console.ReadLine();
hostA.Close();
hostB.Close();
}
Now, if your services are hosted in IIS (webhost), then it's a little harder. Since the "normal" activation requires a .svc file to be part of the endpoint address, and each .svc file is associated with a single class, the address for A would be something like http://machine-name/services/a.svc while the address for B would be something like http://machine-name/services/b.svc. So what you'd need to do in this case is to create a custom ServiceHostFactory, and use the ASP.NET Routes integration to create a .svc-less URL for your service. Then you'd use something similar to the previous example to decide which service will be activated.

How to declaratively implement custom IAuthorizationPolicy in WCF?

I have a WCF service that is hosted in IIS. I want to use my own IAuthorizationPolicy, and have it configured in the web.config file on the server. I have my auth policy:
namespace MyLib.WCF
{
public class CustomAuthorizationPolicy : IAuthorizationPolicy
{
public CustomAuthorizationPolicy()
{
this.Id = Guid.NewGuid().ToString();
}
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
throw new ApplicationException("Testing custom auth");
}
...
}
}
And in my web.config:
<service behaviorConfiguration="Behavior" name="MyService">
<endpoint address="" binding="wsHttpBinding" contract="IMyService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
<serviceBehaviors>
<behavior name="Behavior">
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="MyLib.WCF.CustomAuthorizationPolicy, MyLib.WCF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>
But my CustomAuthorizationPolicy.Evaluate() method never fires. What am I missing?
Well, the obvious (silly) question is: in your <service>, do you actually reference your behavior configuration??
I.e. do you have:
<system.serviceModel>
....
<service name="YourService" behaviorConfiguration="Behavior">
....
</service>
....
</system.serviceModel>
Just defining all your stuff is nice and well - but unless you've actually referenced it, it won't do you any good (been there, done that myself, too! :-) )
Second (almost as silly) question would be: what binding and security config do you use?? Have you even turned on security at all? If you have <security mode="None">, then your service authorization will obviously never be used, either (since no credentials are being passed to the service at all).
Marc