Hi a have WCF service libary with this configuration:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="Default" name="ComDocs.ControlServerServiceLibary.Concrete.TokenService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/TokenService" />
</baseAddresses>
</host>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="basic" binding="basicHttpBinding" contract="ComDocs.ControlServerServiceLibary.Abstract.ITokenService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
If I build it in debug, everything works fine on localhost. But if I make a Windows Service library with the same configuration:
public partial class TokenService : ServiceBase
{
ServiceHost _host = null;
public TokenService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Trace.WriteLine("Starting Token Service...");
_host = new ServiceHost(typeof(TokenService));
_host.Open();
}
protected override void OnStop()
{
Trace.WriteLine("Shutting down Token Service...");
if (_host != null)
{
_host.Close();
_host = null;
}
}
}
Install it with InstallUtil and start it:
but error:
I suspect this line is the culprit.
_host = new ServiceHost(typeof(TokenService));
TokenService is your Windows service class, not your WCF service class.
Related
I have build a simple WCF service using wsDualHttpBinding. It is working fine at local end but it throws a error when I publish the service on a different server and try to consume that service in a WPF project.
Error:
System.ServiceModel.SecurityNegotiationException "The caller was not authenticated by the service."
InnerException:
System.ServiceModel.FaultException "The caller was not authenticated by the service."
Server Config:
<system.serviceModel>
<services>
<service name="VetChat.Service.VetChatService" behaviorConfiguration="wsDualHttpBinding.SampleServiceBehavior">
<!-- Service Endpoints -->
<host>
<baseAddresses>
<add baseAddress="http://service.softprodigy.com:8090/VetChatService.svc"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsDualHttpBinding" contract="VetChat.Service.IVetChatService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="VPS" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="wsDualHttpBinding.SampleServiceBehavior">
<!-- 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"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="VetChat.Service.UserNamePassValidator, VetChat.Service" />
<serviceCertificate findValue="MyName" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Client Config:
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IVetChatService" />
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://service.softprodigy.com:8090/VetChatService.svc"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IVetChatService"
contract="ServiceReference1.IVetChatService" name="WSDualHttpBinding_IVetChatService">
<identity>
<dns value="VPS" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="MyName" x509FindType="FindBySubjectName"
storeLocation="CurrentUser" storeName="TrustedPeople" />
<serviceCertificate>
<defaultCertificate findValue="MyName" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Interface:
[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
public interface IVetChatService
{
[OperationContract(IsOneWay = true)]
void DoWork();
}
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void Notify(string value);
}
Interface Implementation:
public class VetChatService : IVetChatService
{
public void DoWork()
{
//Thread.Sleep(5000);
OperationContext.Current.GetCallbackChannel<ICallback>().Notify("Hello");
}
}
Validte username password service class:
namespace VetChat.Service
{
class UserNamePassValidator :
System.IdentityModel.Selectors.UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName == null || password == null)
{
throw new ArgumentNullException();
}
if (!(userName == UserName && password == Password))
{
//throw new FaultException("Incorrect Username or Password");
}
}
}
public class Service
{
}
}
Call method:
InstanceContext instanceContext = new InstanceContext(new SampleServiceCallback());
ServiceReference1.VetChatServiceClient sampleServiceClient = new ServiceReference1.VetChatServiceClient(instanceContext);
sampleServiceClient.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.TrustedPeople,
X509FindType.FindBySubjectName,
"MyName");
sampleServiceClient.ClientCredentials.UserName.UserName = UserName;
sampleServiceClient.ClientCredentials.UserName.Password = Password;
//sampleServiceClient.Open();
sampleServiceClient.DoWork();
Response Callback:
public class SampleServiceCallback : ServiceReference1.IVetChatServiceCallback
{
#region ISampleServiceCallback Members
public void Notify(string value)
{
MessageBox.Show(value);
}
#endregion
}
Thanks
I have a problem configuring a ServiceBehavior for my WCF service.
Some background.
Basically I am developing a REST service WCF that is supposed to run on IIS.
I need to be able to log exceptions thrown by the service (I'm using log4net) and return HTTP status codes depending on the type of exception.
I want my service implementation to have a minimum knowledge of WCF related stuff, so I don't want to convert the exceptions to FaultException everywhere in the service.
So I figured out that adding my own IErrorHandler to the service host would be the best way to do it.
My problem is however that no matter what I try I can't seem to get the configuration for my custom ServiceBehavior right in Web.config.
Here is the relevant code.
Web config.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
</system.webServer>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="UsingErrorLogBehavior">
<errorLogBehavior/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="errorLogBehavior"
type="MyNameSpace.Web.ErrorExtensionElement, MyNameSpace.Web"/>
</behaviorExtensions>
</extensions>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true"
automaticFormatSelectionEnabled="false"
defaultOutgoingResponseFormat="Json"
maxReceivedMessageSize="4194304" transferMode="Buffered" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
ErrorExtensionElement.
namespace MyNameSpace.Web
{
public class ErrorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(ErrorServiceBehavior); }
}
protected override object CreateBehavior()
{
return new ErrorServiceBehavior();
}
}
}
ErrorServiceBehavior.
namespace MyNameSpace.Web
{
public class ErrorServiceBehavior : IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
{
channelDispatcher.ErrorHandlers.Add(new ExceptionModule());
}
}
public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
}
}
Where ExceptionModule implements IErrorHandler.
You have a <serviceBehavior> section named "UsingErrorLogBehavior", but no service configurations are referencing that section. You can either make that section the default service behavior (by not giving it a name, like you have for the endpoint behavior), or add a <service> element for your service which references that behavior:
<services>
<service name="YourNamespace.YourServiceName"
behaviorConfiguration="UsingErrorLogBehavior">
<endpoint address=""
binding="webHttpBinding"
contract="YourNamespace.YourContractName" />
</service>
</services>
I am hosting WCF as Windows Service using net.tcp. After installing the windows service when I start the service, I get that service was started and stopped.
The error says in order to In order to add an endpoint to the service 'MYService', a non-empty contract name must be specified.
at System.ServiceModel.Description.ConfigLoader.LookupContract(String contractName, String serviceName)
My OnStart function is as follows
protected override void OnStart(string[] args)
{
try
{
if (myServiceHost != null)
{
myServiceHost.Close();
}
myServiceHost = new ServiceHost(typeof(MYservice));
myServiceHost.Open();
}
catch (Exception ex)
{
log.Error("ONStart", ex);
throw;
}
}
The config file is as follows:
<serviceHostingEnvironment minFreeMemoryPercentageToActivateService="10" />
<services>
<service behaviorConfiguration="myServiceBehavior"
name="myNamespace.myTestService">
<endpoint binding="netTcpBinding" bindingConfiguration="netTCPBindingConfig" contract="myNamespace.ServiceInterface.ImyTestService" />
<endpoint binding="mexTcpBinding" bindingConfiguration="" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://10.1.3.69:8523/TestService" />
</baseAddresses>
<timeouts closeTimeout="10:00:10" openTimeout="10:01:00" />
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
In your config file, there is:
<endpoint binding="netTcpBinding" bindingConfiguration="netTCPBindingConfig" contract="myNamespace.ServiceInterface.ISomeService" /> `
Instead of ISomeService, you must specify whichever interface is implemented by MYService.
EDIT
Additionally, mex binding must have a contract specified, i.e. contract="IMetadataExchange"
EDIT AGAIN
For your convenience, this is how your mex binding should look like:
<endpoint binding="mexTcpBinding" address="mex" bindingConfiguration="" contract="IMetadataExchange" />
Please try this:
protected override void OnStart(string[] args)
{
try
{
myServiceHost = new ServiceHost(typeof(MYservice));
myServiceHost.Open();
Console.ReadKey();
}
catch (Exception ex)
{
log.Error("ONStart", ex); throw;
}
finally
{
myServiceHost.Close();
}
}
This is my first WCF service and I am getting an error:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
Code:
namespace WcfMathServiceLibrary
{
[ServiceContract]
public interface IMath
{
[OperationContract]
double Add(double i, double j);
[OperationContract]
double Sub(double i, double j);
[OperationContract]
Complex AddComplexNo(Complex i, Complex j);
[OperationContract]
Complex SubComplexNo(Complex i, Complex j);
}
[DataContract]
public class Complex
{
private int _real;
private int _imaginary;
[DataMember]
public int real { get; set; }
[DataMember]
public int imaginary { get; set; }
}
namespace WcfMathServiceLibrary
{
public class MathService : IMath
{
public double Add(double i, double j)
{
return (i + j);
}
public double Sub(double i, double j)
{
return (i - j);
}
public Complex AddComplexNo(Complex i, Complex j)
{
Complex result = new Complex();
result.real = i.real + j.real;
result.imaginary = i.imaginary + j.imaginary;
return result;
}
public Complex SubComplexNo(Complex i, Complex j)
{
Complex result = new Complex();
result.real = i.real - j.real;
result.imaginary = i.imaginary - j.imaginary;
return result;
}
}
Web.Config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfMathServiceLibrary.MathService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/WcfMathServiceLibrary/MathService/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="WcfMathServiceLibrary.MathService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" >
</endpoint>
</service>
</services>
<behaviors>
<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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
I am not sure what is the issue. Could you please guide me?
I think your contract may need to point to the interface and not the concrete implementation
<endpoint address="" binding="wsHttpBinding" contract="WcfMathServiceLibrary.IMath">
I am working on a WCF REST service that will be hosted within Azure and want to check the user id. To this end I have created a custom ServiceAuthorizationManager.
namespace SecureService
{
public class AccessControlServiceAuthorizationManager : ServiceAuthorizationManager
{
String serviceNamespace = String.Empty;
String acsHostname = String.Empty;
String trustedTokenPolicyKey = String.Empty;
String trustedAudience = String.Empty;
public AccessControlServiceAuthorizationManager()
{
try
{
serviceNamespace = RoleEnvironment.GetConfigurationSettingValue("serviceNamespace");
acsHostname = RoleEnvironment.GetConfigurationSettingValue("acsHostname");
trustedTokenPolicyKey = RoleEnvironment.GetConfigurationSettingValue("trustedTokenPolicyKey");
trustedAudience = RoleEnvironment.GetConfigurationSettingValue("trustedAudience");
}
catch
{
GenerateErrorResponse();
}
finally
{
}
} // end AccessControlServiceAuthorizationManager() Constructor
protected override bool CheckAccessCore(OperationContext operationContext)
{
String headerValue = WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.Authorization];
String token = String.Empty;
string[] nameValuePair = null;
TokenValidator validator = null;
if (String.IsNullOrEmpty(headerValue))
{
GenerateErrorResponse();
return false;
}
if (!headerValue.StartsWith("WRAP "))
{
GenerateErrorResponse();
return false;
}
nameValuePair = headerValue.Substring("WRAP ".Length).Split(new char[] { '=' }, 2);
if (nameValuePair.Length != 2 ||
nameValuePair[0] != "access_token" ||
!nameValuePair[1].StartsWith("\"") ||
!nameValuePair[1].EndsWith("\""))
{
GenerateErrorResponse();
return false;
}
token = nameValuePair[1].Substring(1, nameValuePair[1].Length - 2);
validator = new TokenValidator(acsHostname, serviceNamespace, trustedAudience, trustedTokenPolicyKey);
if (!validator.Validate(token))
{
GenerateErrorResponse();
return false;
}
return true;
}
public void GenerateErrorResponse()
{
}
}
}
My Web.config is as follows;
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="Secure">
<serviceAuthorization serviceAuthorizationManagerType="SecureService.AccessControlServiceAuthorizationManager" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="SecureService.Demo">
<endpoint address="" behaviorConfiguration="webBehavior" binding="webHttpBinding" bindingConfiguration="" contract="SecureService.IDemo" />
<endpoint address="rest" behaviorConfiguration="webBehavior" binding="webHttpBinding" bindingConfiguration="" contract="SecureService.IDemo" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
</system.webServer>
However the CheckAccessCore() method does not seem to be called when I call the service via IE. So the question is how can I ensure it is called and therefore ensure that my users are validated.
I have put a break point in the CheckAccessCore and it never seems to get hit.
And just to make things really interesting - I will need to call this webservice from within Silverlight.
Thanks in advance
Ignore your 'services' section in config. Try:
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint crossDomainScriptAccessEnabled="True" automaticFormatSelectionEnabled="true" helpEnabled="True"/>
</webHttpEndpoint>
</standardEndpoints>
Following the configuration pasted above, I see that service behavior "Secure" is missed to apply on Service. Please check it, if it's not a typo...