How to declaratively implement custom IAuthorizationPolicy in WCF? - 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

Related

Error while opening WCF service host connection

I was unable to open the connection for my ServicHost. I have initially used the 8080 port it worked before.But now it is not working. I see some error (below) with my App.Conifg.Please let me know where the bug in.
This is a simple EmployeeWCF Demo app with the IEmployeeService interface and EmployeeService class.
App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<services>
<service name="EmployeeWCFService.EmployeeService" behaviorConfiguration="mexBehaviour">
<endpoint name ="httpBind" address="EmployeeService" binding="basicHttpBinding" contract="EmployeeWCFService.IEmployeeService" ></endpoint>
<endpoint name ="netTcpBind" address="EmployeeService" binding="netHttpBinding" contract="EmployeeWCFService.IEmployeeService" ></endpoint>
<endpoint name="mexBind" address="mex" binding="mexHttpBinding" contract="IMetadataExchange" ></endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:9090"/>
<add baseAddress="net.tcp://localhost:9093"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehaviour">
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
ConsoleCode:
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(EmployeeWCFService.EmployeeService)))
{
host.Open();
Console.WriteLine("The connection host is opened at the time " + DateTime.Now);
Console.ReadLine();
}
}
}
Error I am Facing while opening WCF Servicehost:
Additional information: A binding instance has already been associated to listen URI 'http://localhost:9090/EmployeeService'. If two endpoints want to share the same ListenUri, they must also share the same binding object instance. The two conflicting endpoints were either specified in AddServiceEndpoint() calls, in a config file, or a combination of AddServiceEndpoint() and config.
There may be a typo in your configuration file. The second service endpoint ought to use NetTcpBinding instead of NetHttpBinding, which causes that the two serivce endpoints has the same listening uri address.
Feel free to contact me if the problem still exists.

Metadata publishing for this service is currently disabled - Again

I'm new to WCF and I've been hitting my head for the past week trying to get everything to work. When browsing the service.svc file I receive the message about the metadata not being enabled. There's hundreds of posts on this but I must be missing something. I think I followed the instructions correctly but I still can't find my error. Where am I going wrong? Any help is appreciated.
service.svc
<%# ServiceHost Service="BiteSizeLearningWS.TranscriptService" Debug="true" %>
web.config
<services>
<service name="BiteSizeLearningWS.iServiceInterface" behaviorConfiguration="TranscriptServiceBehavior">
<endpoint address="" binding="basicHttpBinding" contract="BiteSizeLearningWS.TranscriptService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="TranscriptServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
ServiceContract
namespace BiteSizeLearningWS
{
[ServiceContract (Name="TranscriptService")]
public interface iServiceInterface{...
Implementation
public class TranscriptService : iServiceInterface
Global.asax
namespace BiteSizeLearningWS
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("TranscriptService", new WebServiceHostFactory(), typeof(TranscriptService)));
}
I think you have your:
<service name="BiteSizeLearningWS.iServiceInterface"...
name attribute value and the
<endpoint address="" ... contract="BiteSizeLearningWS.TranscriptService" />
contract attribute value mixed up. Try this:
<service name="BiteSizeLearningWS.TranscriptService"...
and
<endpoint address="" ... contract="BiteSizeLearningWS.iServiceInterface" />
If that works, then what happened is that WCF used the automatic default configuration values for the service instead of the invalid configuration shown in the question. The metadata endpoint is not enabled by default which would be why you're seeing the "disabled" message.

WCF Service host using ServiceHostFactory with Multiple Binding

I have created WCF service to host on IIS.
I am using ServiceHostFactory method to host my service(using Unity as DI).
I want to host my service using multiple binding, over the HTTP as well as over the TCP.
I tried giving base address, but its not taking. still giving me error as Service registered with HTTP schema.
Below code snippet might give you and idea.
public class MyServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(
Type serviceType, Uri[] baseAddresses)
{
MyServiceHost serviceHost = new MyServiceHost(serviceType, baseAddresses);
//configure container
MyFactory.Register();
return serviceHost;
}
}
Config file:
<system.serviceModel>
<services>
<service name="My.Service.MyService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9000/MyService/"/>
<add baseAddress="net.tcp://localhost:9001/MyService/"/>
</baseAddresses>
</host>
<endpoint address="Question" binding="basicHttpBinding" contract="My.Contract.IQuestionContract" />
<endpoint address="Answer" binding="basicHttpBinding" contract="My.Contract.IAnswerContract" />
<endpoint address="Question" binding="netTcpBinding" contract="My.Contract.IQuestionContract" />
<endpoint address="Answer" binding="netTcpBinding" contract="My.Contract.IAnswerContract" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServicebehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="True">
</serviceHostingEnvironment>
Can anyone suggest me what can be done?
Main thing,
Is it possible to host service using ServiceHostFactory with Multiple Binding?
If Yes, can anyone help me how?
I'd try to remove base net.tcp address and specify full address on endpoint.

WCF callback not being executed

I've been Googling this for a day now and can't seem to find the answer. Hoping someone can shed some light on this. I'm trying to implement a simple WCF client-server callback, with console apps at both the client and server sides. The operation executes on the server and everything seems to work fine except that the callback doesn't execute on the client. I.e. it never writes "Callback called!!!", and a breakpoint placed in the callback never trips. The client simply writes "Done." and waits for user input.
I'm sure it's something simple. Any help would be greatly appreciated. Thanks!
//SERVER CODE:
namespace NodeServiceLib
{
public interface ISomeCallbackContract
{
[OperationContract]
void OnCallback();
}
[ServiceContract(CallbackContract = typeof(ISomeCallbackContract))]
public interface IMyContract
{
[OperationContract]
void DoSomething();
}
public class NodeService : IMyContract
{
public void DoSomething()
{
Console.WriteLine("I'm doing something!!!");
}
}
}
<configuration>
<system.web>
<compilation debug="true"/>
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<bindings/>
<services>
<service name="NodeServiceLib.NodeService" behaviorConfiguration="MEX">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/Node" />
<add baseAddress="net.tcp://localhost:8001/Node" />
</baseAddresses>
</host>
<endpoint
address="MyContract"
binding="netTcpBinding"
contract="NodeServiceLib.IMyContract"
/>
<endpoint
address="MEX"
binding="mexHttpBinding"
contract="IMetadataExchange"
/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MEXGET">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
<behavior name="MEX">
<serviceMetadata/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup</configuration>
//CLIENT CODE:
namespace TestConsole
{
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class Callback : NodeServices.IMyContractCallback
{
public void OnCallback()
{
Console.WriteLine("Callback called!!!");
}
}
class Program
{
static void Main(string[] args)
{
System.Threading.Thread.Sleep(5000); // Give server time to spin up
Console.WriteLine("=== CLIENT ===");
InstanceContext context = new InstanceContext(new Callback());
NodeServices.MyContractClient proxy = new NodeServices.MyContractClient(context);
proxy.DoSomething();
Console.WriteLine("Done.");
Console.ReadLine();
}
}
}
Shouldn't you be calling the callback method in the server's DoSomething method?

How to use a WCF service with HTTP Get (within Visual studio 2010)

We've tried to use a very very simple WCF service with a HTTp Get and we can't get it work.
We've followed those "guide" but it doesn't work
http://msdn.microsoft.com/en-us/library/bb412178.aspx
http://www.dotnetfunda.com/articles/article779-simple-5-steps-to-expose-wcf-services-using-rest-style-.aspx
When we call our service with the following url, we get a page not found error:
http://localhost:9999/Service1.svc/GetData/ABC
The base url (http://localhost:9999/Service1.svc) works fine and returns the wcf service information page correctly.
Those are the steps and code to reproduce our example.
In Visual Studio 2010, create a new "WCF Service Application" Project
Replace the IService interface with this code
[ServiceContract()]
public interface IService1
{
[OperationContract()]
[WebInvoke(Method = "GET",
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "GetData/{value}")]
string GetData(string value);
}
Replace the Service class with this code
public class Service1 : IService1
{
public string GetData(string value)
{
return string.Format("You entered: {0}", value);
}
}
The web.config look like this
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="Service1">
<endpoint address="" binding="webHttpBinding" contract="IService1" behaviorConfiguration="WebBehavior1">
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebBehavior1">
<webHttp helpEnabled="True"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
Press Run and try to call the Get method
If someone get this or something similar working, it would be very kind if you could reply information about the working example.
Thank you very much
I recreated your sample - works like a charm.
One point: do your service contract (public interface IService1) and service implementation (public class Service1 : IService1) exist inside a .NET namespace??
If so, you need to change your *.svc and your web.config to include:
<services>
<service name="Namespace.Service1">
<endpoint address="" binding="webHttpBinding"
contract="Namespace.IService1"
behaviorConfiguration="WebBehavior1">
</endpoint>
</service>
</services>
The <service name="..."> attribute and the <endpoint contract="..."> must include the .NET namespace for this to work.