No endpoints found when adding a Custom ServiceHostFactory - wcf

I created a wcf application. I didn't change anything. Used the Service1.GetData(int). It works fine. I can hit the wsdl in a browser and everything. Then I created a custom service host factory that simply returns a new service host and the service never comes up. I can no longer get to the wsdl in a browser. I tried adding a Custom ServiceHost so I could do a little debugging and it appears that there are no endpoints being found (even when explicitly calling AddDefaultEndpoints(). This is true even when I explicitly add the endpoint to the web.config.
Does anyone have any ideas as to what the issue could be?
If anyone cares to take a look I put the code on github: https://github.com/devlife/Sandbox/tree/master/WcfService1

Why are you using ServiceHostFactory?
are you going to use AppFabric/IIS? or self hosted services?
I think you need to add a MEX endpoint.
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />

Here is how I have defined a CustomHost in a project I am working on,
<%# ServiceHost Language="C#" Debug="true" Service="Servicename.Servicename" CodeBehind="Service1.svc.cs" Factory="WcfService1.CustomServiceHostFactory"%>
And this,
public class CustomServiceHostFactory : ServiceHostFactory
{
public CustomServiceHostFactory()
{
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new CustomServiceHost(serviceType, baseAddresses);
}
}
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost()
{
}
public CustomServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void OnOpening()
{
base.OnOpening();
}
protected override void OnClosing()
{
base.OnClosing();
}
protected override void ApplyConfiguration()
{
base.ApplyConfiguration();
}
}
Note that the CustomServiceHost looks bare, but that is because my solution has a lot of logging and configuration in this CustomServiceHost that I removed and is not appropriate.
The other difference I can see also is that my CustomServiceHost does not add the endpoint. The endpoint is defined in the config file like this,
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Servicename.Servicename" behaviorConfiguration="ServiceBehavior">
<endpoint address="http://*******.svc" binding="wsHttpBinding" contract="Namespace.IContract" bindingConfiguration="BindingConfig">
</endpoint>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="BindingConfig" maxReceivedMessageSize="9291456">
<security mode="None">
</security>
<readerQuotas maxArrayLength="6291456" />
</binding>
</wsHttpBinding>
</bindings>

Related

Inject an object into a custom WCF UserNamePassValidator - Autofac

I have a service which is hosted in IIS. It is configured by Web.config.
I have created a custom UserNamePassValidator which works if I I have the logic in the validate method. But I want the logic in another project and injected in using DI as below.
public class UserNamePassValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
{
private readonly ISystemAuthentication _systemAuthentication;
public UserNamePassValidator(ISystemAuthentication systemAuthentication)
{
_systemAuthentication = systemAuthentication;
}
public override void Validate(string userName, string password)
{
_systemAuthentication.Validate(userName, password))
}
}
I am using the Autofac WCF integration.
var builder = new ContainerBuilder();
builder.RegisterType<AuthenticationService>().As<IAuthenticationService>();
builder.Register(c => new SystemAuthentication()).As<ISystemAuthentication>();
builder.Register(c => new UserNamePassValidator(c.Resolve<ISystemAuthentication>()));
AutofacHostFactory.Container = builder.Build();
When I browse to the service i receive the following error:
[MissingMethodException: No parameterless constructor defined for this object.]
web.config behaviour;
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
I have read the following related post but the example is a self hosted service:
How to inject an object into a WCF validator class
EDIT
<system.serviceModel>
<services>
<service behaviorConfiguration="Namespace.AuthenticationServiceBehaviour" name="Namespace.AuthenticationService" >
<endpoint address="" binding="wsHttpBinding" contract="Namespace.IAuthenticationService" bindingConfiguration="SafeServiceConf">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Namespace.AuthenticationServiceBehaviour">
<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="true" />
<serviceCredentials>
<serviceCertificate findValue="AuthenticationService"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Namespace.UserNamePassValidator, Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="SafeServiceConf" maxReceivedMessageSize="65536">
<readerQuotas maxStringContentLength="65536" maxArrayLength="65536" maxBytesPerRead="65536" />
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
SystemAuthentication class
public class SystemAuthentication : ISystemAuthentication
{
public bool Validate(string userName, string password)
{
// removed code for abbreviation
return true;
}
WCF Authentication Service
public class AuthenticationService : IAuthenticationService
{
public bool Authenticate(string email, string password)
{
// removed for abbreviation
return true;
}
}
From the help of this post UserNamePasswordValidator: When DI and Framework collide
From the XML configuraiton i removed:
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
I added the behaviour to the AutoFacHostFactory service host
IContainer container = builder.Build();
AutofacHostFactory.Container = container;
AutofacHostFactory.HostConfigurationAction = host =>
{
var auth = host.Credentials.UserNameAuthentication;
auth.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
auth.CustomUserNamePasswordValidator = container.Resolve<UserNamePassValidator>();
};
This works perfectly, but it would have been nicer to be able to do it from the web.config. If anyone knows a better way please post :)

Self hosting WCF contract not found

I used this MSDN example to construct my console host app:
http://msdn.microsoft.com/en-us/library/ms731758.aspx
It works I have a service running, while running I can add it as a Service Reference to my Silverlight class library ViewModel and I can see it running in a browser.
However when I run my Silverlight app I get the following error message:
Could not find default endpoint element that references contract
'ServiceLayer.IServiceLayer' in the ServiceModel client configuration
section. This might be because no configuration file was found for
your application, or because no endpoint element matching this
contract could be found in the client element.
This is my service code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Model;
namespace ServiceLayer
{
[ServiceContract(Namespace = "ServiceLayer")] //This has to match references or updating the service reference will not work.
public interface IServiceLayer
{
[OperationContract] //This is needed for each method.
string Compile(string cscode, string name, string type, int token);
[OperationContract] //This is needed for each method.
string LoginClick(string username, string password, bool createuser, int token);
[OperationContract]
bool IsLoggedIn(int token);
[OperationContract] //This is needed for each method.
object[] GetMessages(int token);
[OperationContract] //This is needed for each method.
int GetToken(int token);
[OperationContract] //This is needed for each method.
string[][] GetPlugins(int token);
[OperationContract] //This is needed for each method.
string Finalize(int token, string[] descriptions);
[OperationContract] //This is needed for each method.
object[][] Communicate(string methodName, int token, object[] args);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ServiceLayer : IServiceLayer
{
public string Compile(string cscode, string name, string type, int token)
{
// Add your operation implementation here
ModelInterface MI = new ModelInterface();
return MI.Compile(cscode, name, type, token);
}
public String LoginClick(string username, string password, bool createuser, int token)
{
ModelInterface MI = new ModelInterface();
return MI.LoginClick(username, password, createuser, token);
}
public bool IsLoggedIn(int token)
{
ModelInterface MI = new ModelInterface();
return MI.IsLoggedIn(token);
}
public object[] GetMessages(int token)
{
ModelInterface MI = new ModelInterface();
return MI.GetMessages(token);
}
public int GetToken(int token)
{
ModelInterface MI = new ModelInterface();
return MI.GetToken(token);
}
public string[][] GetPlugins(int token)
{
ModelInterface MI = new ModelInterface();
return MI.GetPlugins(token);
}
public string Finalize(int token, string[] descriptions)
{
ModelInterface MI = new ModelInterface();
return MI.Finalize(token, descriptions);
}
public object[][] Communicate(string methodName, int token, object[] args)
{
ModelInterface MI = new ModelInterface();
return MI.Communicate(methodName, token, args);
}
// Add more operations here and mark them with [OperationContract]
}
}
This is the ServiceReferences.ClientConfig of the ViewModel:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IServiceLayer" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
<binding name="BasicHttpBinding_IServiceLayer1" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:3263/front" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IServiceLayer" contract="IServiceLayer"
name="BasicHttpBinding_IServiceLayer" />
<endpoint address="http://localhost:3263/front" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IServiceLayer1" contract="ServiceLayer.IServiceLayer"
name="BasicHttpBinding_IServiceLayer1" />
</client>
</system.serviceModel>
And this is the Web.Config file of the project with the website hosting the Silverlight app.
I post it because I tried this Could not find default endpoint element
guide - ie copying the servicemodel section from the VM config to the web.Config below also:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<pages controlRenderingCompatibilityVersion="4.0"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="OrgOS.Web.ServerCommunicationService.customBinding0">
<binaryMessageEncoding/>
<httpTransport/>
</binding>
<binding name="OrgOS.Web.ServiceLayer.customBinding0">
<binaryMessageEncoding/>
<httpTransport/>
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<services>
<service name="OrgOS.Web.ServiceLayer">
<endpoint address="" binding="customBinding" bindingConfiguration="OrgOS.Web.ServiceLayer.customBinding0" contract="OrgOS.Web.ServiceLayer"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
My server I rented came without ASP.NET despite the fact I paid for it, support is on leave and I have deadlines coming up!
Trying to get WCF working is driving me mad - please help me...
Why is it so freaking hard to show a simple Silverlight project...
Ah nevermind; you have to post the config settings in both the View Silverlight project, the web project AND the ViewModel Silverlight project.
You must also delete all endpoints and bindings, but one to avoid getting things confused.
Also changed things to make sure namespace="namespace" fits the actual namespace.
... not that things work for that reason, oh noes all I get is invalid results.
FML right now.

How do I set bindingNamespace when using fileless activation?

I'm attempting to eliminate tempuri.org from my WCF service, hosted in IIS using fileless activation. I've followed the instructions here, and I'm stuck when it comes to the bindingNamespace attribute in Web.config, because I'm using fileless activation.
My Web.config merely contains:
<serviceActivations>
<add relativeAddress="Foo.svc"
service="BigCorp.Services.Foo, BigCorp.Services"
/>
</serviceActivations>
I therefore don't have an <endpoint> node on which to set bindingNamespace.
What to do?
You can still use the <services> and hence <endpoint> nodes with WCF File-less activation. Take a look at the following example, where I even modify the default wsHttpBinding to add transport security and enable default behaviors as well; all for the file-less activation of the "Module1.DES.ExternalDataService" service.
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding messageEncoding="Mtom">
<security mode="Transport"/>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Module1.DES.ExternalDataService">
<endpoint binding="wsHttpBinding" bindingNamespace="" contract="Module1.DES.IExternalDataService"/>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="ExternalDataService.svc" service="Module1.DES.ExternalDataService"/>
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
Hope this helps.
To change the binding namespace you can use a custom factory (instead of the default one provided) where you can change all the properties of the binding:
<serviceActivations>
<add relativeAddress="Foo.svc"
service="BigCorp.Services.Foo, BigCorp.Services"
factory="BigCorp.Services.FooHostFactory, BigCorp.Services"/>
</serviceActivations>
And the factory:
public class FooHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new FooServiceHost(serviceType, baseAddresses);
}
}
public class FooServiceHost : ServiceHost
{
public FooServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses) { }
protected override void OnOpening()
{
base.OnOpening();
foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
{
if (!endpoint.IsSystemEndpoint)
{
endpoint.Binding.Namespace = "http://services.bigcorp.com/foo";
}
}
}
}
In your service code, you specify:
[ServiceContract(Namespace="http://your-url")]
public interface IMyInterface { ... }
and you can also specify it for data contracts:
[DataContract(Namespace="http://your-url/data")]
public class MyData { ... }
Besides the obvious change of service/data contract namespaces, you can also set a namespace on the Binding object itself, as well as a namespace on the service description:
Binding binding = new BasicHttpBinding();
binding.Namespace = "urn:binding_ns";
ServiceHost host = new ServiceHost(typeof(MyService), address);
var endpoint = host.AddServiceEndpoint(typeof(IMyService), binding, "");
host.Description.Namespace = "urn:desc_ns";
The latter one is what controls the targetNamespace of the WSDL document itself.
In the end, I used a custom BindingNamespaceAttribute, derived from this example.
If you are using the fileless service activation feature of WCF 4.0 via the serviceActivations config element, then you can override the AddDefaultEndpoints base method in your ServiceHost implementation.
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace MyApp.WS.WCFServiceHost
{
public class MyHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new EDOServiceHost(serviceType, baseAddresses);
}
}
public class MyServiceHost : ServiceHost
{
public EDOServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses) { }
public override System.Collections.ObjectModel.ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints()
{
var endpoints = base.AddDefaultEndpoints();
foreach (ServiceEndpoint endpoint in endpoints)
{
if (!endpoint.IsSystemEndpoint)
{
endpoint.Binding.Namespace = NamespaceConstants.MyNamespace;
}
}
return endpoints;
}
}
}
Or you could just use config only, the only down side to that is you violate the DRY principle slightly since you now have two points to maintain the namespace string, one in your constants and one in the config file.
In the following example im using the WCFExtrasPlus behaviour to 'flatten' the WSDL. You don't need this if your deploying to a .net 4.5 IIS7 server as you will have access to a flat WSDL anyway which is a new feature built into the 4.5 framework, I digress.
The example also assumes two service contracts and two service behaviour implementations of those contracts.
<system.serviceModel>
<services>
<service name ="MyApp.WS.ServiceBehaviour.Enquiries">
<endpoint bindingNamespace="MyApp.WS" binding="basicHttpBinding" contract="MyApp.WS.ServiceContract.IEnquiries" />
</service>
<service name ="MyApp.WS.ServiceBehaviour.CallLogging">
<endpoint bindingNamespace="MyApp.WS" binding="basicHttpBinding" contract="MyApp.WS.ServiceContract.ICallLogging" />
</service>
</services>
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="Enquiries.svc"
service="MyApp.WS.ServiceBehaviour.Enquiries"
/>
<add relativeAddress="CallLogging.svc"
service="MyApp.WS.ServiceBehaviour.CallLogging"
/>
</serviceActivations>
</serviceHostingEnvironment>
<extensions>
<behaviorExtensions> <!-- The namespace on the service behaviour, the service contract, the data contract and the binding must all be set to the same.-->
<add name="wsdlExtensions" type="WCFExtrasPlus.Wsdl.WsdlExtensionsConfig, WCFExtrasPlus, Version=2.3.1.8201, Culture=neutral, PublicKeyToken=f8633fc5451b43fc" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior>
<wsdlExtensions singleFile="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- 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="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
For reference the service contracts;
[ServiceBehavior(Namespace = NamespaceConstants.MyNamespace)]
public class CallLogging : ICallLogging
{
}
[ServiceBehavior(Namespace = NamespaceConstants.MyNamespace)]
public class Enquiries : IEnquiries
{
}
NB: A namespace does not need http:// in its name. It can be the namespace of your project if you like i.e. MyApp.MyProject.Somthing . See URN

My IIS does not recognize my WCF custom binding

Today, I have a problem with hosting my custom service host using custom binding. I have tried to implement ServiceHostFactory but when i right click to view with in browser, the error appeared as IIS does not recognize my custom binding (duplexHttpBinding).
My web.config is here:
<services>
<service name="TestWcf.Service1"
behaviorConfiguration="Service1Behavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/Service1"/>
</baseAddresses>
</host>
<endpoint
address="http://localhost:9999/Service1"
binding="duplexHttpBinding"
bindingConfiguration="binding1"
contract="TestWcf.IService" />
</service>
</services>
<bindings>
<duplexHttpBinding>
<binding name="binding1"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="24.20:31:23.6470000"
sendTimeout="02:01:00"
session="ReliableSession"
sessionTimeout="00:10:00"
maxUndeliveredMessages="100"
maxMessagesInBatch="10"
maxPollingReplyInterval="00:02:00">
</binding>
</duplexHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Service1Behavior">
<serviceMetadata httpGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
and code in dervied class is here:
public class CustomServiceHost : ServiceHostFactory
{
public override ServiceHostBase CreateServiceHost(string service, Uri[] baseAddresses)
{
DuplexHttpBinding binding = new DuplexHttpBinding();
binding.Name = "binding1";
Uri baseAddress = new Uri("http://localhost:8888/Service1");
Uri address = new Uri("http://localhost:9999/Service1");
ServiceHost serviceHost = new ServiceHost(typeof(Service1), baseAddresses);
serviceHost.AddServiceEndpoint(typeof(IService1), binding, address);
return serviceHost;
}
}
and in SVC file
<%# ServiceHost Language="C#" Debug="true" Service="TestWcf.Service1" Factory="TestWcf.CustomServiceHost" %>
Do I miss something in the context?
Thank you.
You must register new binding as binding extension in your configuration file.

Subscribing to TFS events and WCF

Sorry for asking a question about something I don't know much about, but I've been pulling my hair out trying to get this working.
So, I have a WCF service that is hosted on IIS and seems to be working insomuch that I can "see" it on the network by going to http://servername/MyService.svc in a browser.
That .svc looks like:
<% #ServiceHost Service="Foo.Bar" %>
The relevant code looks like:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06Services/Notification/03")]
public interface IBar
{
[OperationContract(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*")]
[XmlSerializerFormat(Style = OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml);
}
and:
public class Bar : IBar
{
public void Notify(string eventXml, string tfsIdentityXml)
{
// Just some test output to see if it worked
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "tfs.txt");
File.WriteAllText(path, tfsIdentityXml + eventXml);
}
}
That's all been built and the ensuing .dll put into the bin dir in the site root in IIS.
I now want to subscribe via bissubscribe.exe (or a similar method) to TFS check-in events. I tried doing something like:
bissubscribe /eventType CheckinEvent
/address http://servername/MyService.svc
/deliveryType Soap
/server mytfsserver
But nothing; it doesn't even look like there was log activity. So keeping in mind I know nothing about WCF, what am I doing wrong? I imagine the address param is one thing; am I not supposed to point it to the .svc?
I have created a blog post how you can use WCF in combination with the Event Services of TFS: http://www.ewaldhofman.nl/post/2010/08/02/How-to-use-WCF-to-subscribe-to-the-TFS-2010-Event-Service-rolling-up-hours.aspx
TFS 2010 and WCF 4.0 configurations are described below...
Method signature:
public void Notify(string eventXml) /* No SubscriptionInfo! */
Web config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="Microsoft.TeamFoundation, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
</assemblies>
</compilation>
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="NotificationServiceBehavior" name="TF.CheckinListener.CheckinListener">
<endpoint address="Notify" binding="wsHttpBinding" bindingConfiguration="noSecurity" contract="TF.CheckinListener.ICheckinListener" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="NotificationServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
</binding>
<wsHttpBinding>
<binding name="noSecurity" maxBufferPoolSize="20000000" maxReceivedMessageSize="200000000">
<readerQuotas maxStringContentLength="200000000" maxArrayLength="200000000" />
<security mode="None" />
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Subscription address for bissubscribe:
http://MachineName/VirtualDirectoryName/Service.svc/Notify
One point that jumps out is the fact you have a method that doesn't return anything except void. Those should be marked as "one-way" method in WCF:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06Services/Notification/03")]
public interface IBar
{
[OperationContract(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*", IsOneWay=true)]
[XmlSerializerFormat(Style = OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml);
}
Add the "IsOneWay=true" to your [OperationContract] attribute.
Other than that, there's nothing obviously wrong in your code, but to really tell, we'd need a lot more config info to really tell. Try the IsOneWay=true first and see if that solves your issue.
How is your service configured? In particular, is it configured to use basicHttpBinding?
Try creating a client to call your service to make sure it can be called.
Then, see if there's an example service from the TFS SDK - see if you can get the example to work.
I was able to complete this connection with the following:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
public interface ITeamSystemObserver : IObservable
{
[OperationContract( Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*" )]
[XmlSerializerFormat(Style=OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml, SubscriptionInfo SubscriptionInfo);
}
Note you are missing the SubscriptionInfo parameter. Here is my web.config:
<basicHttpBinding>
<binding name="TfsEventServiceBasic">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>