WCF/Windows Service not working - wcf

I'm trying to create a windows service along with WCF. We don't want to use IIS to handle the proxying of the service. I've gotten the service registered and started. I created a simple console application to call the service, but it times out.
I have a .NET DLL containing functions that call a locally running application to create an alarm record. I created a forms application that uses AlarmLib.dll and it is able to make the call and insert the alarm record.
It appears to be a permissions issue. I get the following exception:
> Unhandled Exception: System.ServiceModel.EndpointNotFoundException:
> Could not co nnect to http://localhost:8000/ServiceModel/service. TCP
> error code 10061: No co nnection could be made because the target
> machine actively refused it 127.0.0.1:
> 8000. ---> System.Net.WebException: Unable to connect to the remote
> server ---> System.Net.Sockets.SocketException: No connection could
> be made because the tar get machine actively refused it
> 127.0.0.1:8000
> at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot,
> SocketAddre ss socketAddress) at
> System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP) at
> System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,
> Sock et s4, Socket s6, Socket& socket, IPAddress& address,
> ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout,
> Exception& exception) --- End of inner exception stack trace
> at System.Net.HttpWebRequest.GetRequestStream(TransportContext&
> context) at System.Net.HttpWebRequest.GetRequestStream() at
> System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.GetOutputStre
> am() --- End of inner exception stack trace ---
I ran VS2010 as an administrator. Any other settings for the service that I can modify?
Thanks,
John
Windows service code:
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using System.Configuration;
using System.Configuration.Install;
using AlarmLib;
namespace Test.ServiceModel
.WindowsServices {
//
Define a service contract.
[ServiceContract(Namespace = "http://ServiceModel.WindowsServices")]
public interface IAlarmLib {
[OperationContract]
bool CreateNoDataAlarm(string well, string run, string record, string description, string selectedVariable);
}
// Implement the IAlarmLib service contract in a service class.
public class AlarmLibService : IAlarmLib {
// Implement the IAlarmLib methods.
public bool CreateNoDataAlarm(string well, string run, string record, string description, string sel
ectedVariable) {
AlarmUserConfiguration newalarm = new AlarmUserConfiguration();
// The Machine name should be the machine which is running the client application
// and which calls the webservice. This should not be the name of machine hosting
// webservice.
newalarm.MachineName = System.Environment.MachineName;
newalarm.AlarmType = AlarmTypes.NoData;
newalarm.TimeInSeconds = 30;
DateTime CreationTime = DateTime.Now;
newalarm.Name = "NoDataAlarm " + CreationTime.ToString();
PrimaryKey key = new PrimaryKey();
key.Well = "Well ID 1";
key.Run = "1600";
key.Record = "DGR";
key.Desc = "Realtime";
key.SelectedVariable = "Gamma Ray A";
newalarm.PrimaryKeys = key;
// Add any of the following activities.
/*"All"
"Trip Out"
"Trip In"
"Circulating"
"Drilling On Bottom"
"Drilling Off Bottom"*/
newalarm.TDActivities.Add("Drilling On Bottom");
bool bStatus = AlarmUtilities.AddNewAlarm(newalarm, "-Local-");
return bStatus;
}
}
public class AlarmLibWindowsService : ServiceBase {
public ServiceHost serviceHost = null;
public AlarmLibWindowsService() {
// Name the Windows Service
ServiceName = "AlarmLibWS";
}
public static void Main() {
ServiceBase.Run(new AlarmLibWindowsService());
}
// Start the Windows service.
protected override void OnStart(string[] args) {
if (serviceHost != null) {
serviceHost.Close();
}
// Create a ServiceHost for the AlarmLibService type and
// provide the base address.
serviceHost = new ServiceHost(typeof(AlarmLibService));
// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
}
protected override void OnStop() {
if (serviceHost != null) {
serviceHost.Close();
serviceHost = null;
}
}
}
// Provide the ProjectInstaller class which allows
// the service to be installed by the Installutil.exe tool
[RunInstaller(true)]
public class ProjectInstaller : Installer {
private ServiceProcessInstaller process;
private ServiceInstaller service;
public ProjectInstaller() {
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
service = new ServiceInstaller();
service.ServiceName = "AlarmLibWS";
Installers.Add(process);
Installers.Add(service);
}
}
}
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!-- This section is optional with the new configuration model
introduced in .NET Framework 4. -->
<service name="ServiceModel.WindowsServices.AlarmLibService" behaviorConfiguration="AlarmLibServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModel/service"/>
</baseAddresses>
</host>
<!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/ServiceModel/service -->
<endpoint address=""
binding="wsHttpBinding"
contract="ServiceModel.WindowsServices.IAlarmLib" />
<!-- the mex endpoint is exposed at http://localhost:8000/ServiceModel/service/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="AlarmLibServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Console app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestAlarmLibConsoleApp {
class Program {
static void Main(string[] args) {
ServiceReference1.AlarmLibClient client = new ServiceReference1.AlarmLibClient();
bool result = client.CreateNoDataAlarm("Well ID 1", "1100", "DGR", "Realtime", "Gamma Ray A");
Console.WriteLine("result = " + bool.TrueString);
}
}
}
Here is the code in forms app that works:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using AlarmLib;
namespace TestCallingAlarmLib {
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
bool result = CreateNoDataAlarm();
Application.Run(new Form1());
}
static bool CreateNoDataAlarm() {
AlarmUserConfiguration newalarm = new AlarmUserConfiguration();
// The Machine name should be the machine which is running the client application
// and which calls the webservice. This should not be the name of machine hosting
// webservice.
newalarm.MachineName = System.Environment.MachineName;
newalarm.AlarmType = AlarmTypes.NoData;
newalarm.TimeInSeconds = 30;
DateTime CreationTime = DateTime.Now;
newalarm.Name = "NoDataAlarm " + CreationTime.ToString();
PrimaryKey key = new PrimaryKey();
key.Well = "Well ID 1";
key.Run = "1100";
key.Record = "DGR";
key.Desc = "Realtime";
key.SelectedVariable = "Gamma Ray A";
newalarm.PrimaryKeys = key;
// Add any of the following activities.
/*"All"
"Trip Out"
"Trip In"
"Circulating"
"Drilling On Bottom"
"Drilling Off Bottom"*/
newalarm.TDActivities.Add("Drilling On Bottom");
bool bStatus = AlarmUtilities.AddNewAlarm(newalarm, "-Local-");
return bStatus;
}
}
}

Check your Client Access Policy, make sure you have the ports opened up on the server and double check your firewall. Every single time I get this error it's related to one of those.

Related

How to fix AddressInUseException that occurs whenever service host is opened

I am working on WCF windows application... while restarting the service, I am getting the below exception.
outerType: System.ServiceModel.AddressAlreadyInUseException
outerMessage: "Cannot listen on pipe name 'net.pipe://0.0.0.1/MyService' because another pipe endpoint is already listening on that name."
type: System.IO.PipeException
App.Config file:
<services>
<service name="ServiceName">
<endpoint address="" binding="netNamedPipeBinding" contract="ServiceClient">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.pipe://0.0.0.1/MyService"/>
</baseAddresses>
</host>
</service>
</services>
Start Method:
public void Start(string serviceName)
{
_serviceName = serviceName;
if (_serviceController == null)
{
_serviceController = new ServiceController(_serviceName);
}
TimeSpan timeout;
switch (_serviceController.Status)
{
case ServiceControllerStatus.Stopped:
_serviceController.Start();
timeout = TimeSpan.FromMilliseconds(60000);
_serviceController.WaitForStatus(ServiceControllerStatus.Running, timeout);
break;
case ServiceControllerStatus.Paused:
_serviceController.Continue();
timeout = TimeSpan.FromMilliseconds(60000);
_serviceController.WaitForStatus(ServiceControllerStatus.Running, timeout);
break;
}
}
Stop Method:
public void Stop()
{
if (_serviceController == null)
{
_serviceController = new ServiceController(_serviceName);
}
if (_serviceController.Status == ServiceControllerStatus.Running)
{
_serviceController.Stop();
TimeSpan timeout = TimeSpan.FromMilliseconds(20000);
_serviceController.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
}
}
When ever I restarts my service, I will start my Service controller and also open a service host for hosting my service.
_serverHost = new ServiceHost(this); // this points my service name mentioned in App.Config
_serverHost.Open(); // Exception occurs here.
I tried to increase my time out in WaitForStatus() on both Stop() method but it didn't worked out.
Any suggestion will be a great help.
Thanks.
Since you merely post a management application of the window NT service, I don’t think any changes on this side would help.
What is the Windows NT service code design? In my opinion, we should open and close the service host properly in the windows service OnStart event and windows service OnStop event. Windows NT service is the root of the issue.
Besides, I suggest add the IF statement detection during opening the service host and stop the service host.
Please consider the below code.
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
Uri uri = new Uri("net.pipe://localhost/mypipe");
ServiceHost sh = null;
protected override void OnStart(string[] args)
{
NetNamedPipeBinding binding = new NetNamedPipeBinding();
try
{
if (sh == null)
{
sh = new ServiceHost(typeof(MyService), uri);
sh.Open();
} }
catch (Exception e)
{
}
}
protected override void OnStop()
{
if (sh != null && sh.State == CommunicationState.Opened)
{
sh.Close();
}
}
Feel free to let me know if the problem still exists.

how to find the service address in WCF client

I created a WCF service and client in same machine, the services address is wrote into Client's code, so I can easily find the service and create connection to service.
Then I try to deploy them into Intranet. The first problem is: how could Client find the address of server. In actual environment, customers can install service at any computer in Intranet, is there any way to let client find the server address?
WCF service could expose a specific endpoint as a discovery endpoint to all clients so that client could find where the service lies. You could even use UDP multicast to enable the service to be discovered by the client.
You could check the official document.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/wcf-discovery
I have made a demo, wish it is useful to you.
Server.
class Program
{
static void Main(string[] args)
{
using (ServiceHost sh=new ServiceHost(typeof(MyService)))
{
sh.Open();
Console.WriteLine("serivce is ready...");
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string SayHello();
}
public class MyService : IService
{
public string SayHello()
{
return "Hello, I am a Clown";
}
}
Server app.config
<system.serviceModel>
<services>
<service name="DiscoveryEndpoint20181024.MyService" behaviorConfiguration="mybehavior">
<endpoint address="http://10.157.18.188:4800" binding="wsHttpBinding" contract="DiscoveryEndpoint20181024.IService"></endpoint>
<endpoint kind="discoveryEndpoint" address="http://localhost:9999" binding="wsHttpBinding"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mybehavior">
<serviceMetadata />
<serviceDiscovery />
</behavior>
</serviceBehaviors>
</behaviors>
Client.
class Program
{
static void Main(string[] args)
{
DiscoveryClient client = new DiscoveryClient("my_client");
client.ClientCredentials.Windows.ClientCredential.UserName = "administrator";
client.ClientCredentials.Windows.ClientCredential.Password = "abcd1234!";
FindCriteria crit = new FindCriteria(typeof(IService));
FindResponse resp = client.Find(crit);
if (resp != null && resp.Endpoints.Count > 0)
{
EndpointDiscoveryMetadata epaddrMtd = resp.Endpoints[0];
ChannelFactory<IService> factory = new ChannelFactory<IService>(new WSHttpBinding(), epaddrMtd.Address);
factory.Credentials.Windows.ClientCredential.UserName = "administrator";
factory.Credentials.Windows.ClientCredential.Password = "abcd1234!";
IService service = factory.CreateChannel();
var result=service.SayHello();
Console.WriteLine(result);
Console.ReadLine();
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string SayHello();
}
class DemoService : IService
{
public string SayHello()
{
OperationContext context = OperationContext.Current;
return $"the address:{OperationContext.Current.Channel.LocalAddress.Uri}";
}
}
Client.config
<system.serviceModel>
<client>
<endpoint name="my_client" kind="discoveryEndpoint" address="http://10.157.18.188:9999" binding="wsHttpBinding"></endpoint>
</client>
</system.serviceModel>

How to Host SVC file in win form apps WCF

i am new in WCF. i know how to host wcf service in windows form. now i develop a small wcf service which has .svc file. i want to host this svc file in win form. so just want to know process will be same or different?
here is my svc file markup
<%# ServiceHost Language="C#" Debug="true"
Service="Services.ChatService" CodeBehind="ChatService.svc.cs" %>
here is small code inside svc file code behind file
namespace Services
{
/// <summary>
/// Implements the chat service interface.
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ChatService : IChatService
{
private readonly Dictionary<Guid, IChatServiceCallback> clients =
new Dictionary<Guid, IChatServiceCallback>();
#region IChatService
Guid IChatService.Subscribe()
{
IChatServiceCallback callback =
OperationContext.Current.GetCallbackChannel<IChatServiceCallback>();
Guid clientId = Guid.NewGuid();
if (callback != null)
{
lock (clients)
{
clients.Add(clientId, callback);
}
}
return clientId;
}
void IChatService.Unsubscribe(Guid clientId)
{
lock (clients)
{
if (clients.ContainsKey(clientId))
{
clients.Remove(clientId);
}
}
}
void IChatService.KeepConnection()
{
// Do nothing.
}
void IChatService.SendMessage(Guid clientId, string message)
{
BroadcastMessage(clientId, message);
}
#endregion
/// <summary>
/// Notifies the clients of messages.
/// </summary>
/// <param name="clientId">Identifies the client that sent the message.</param>
/// <param name="message">The message to be sent to all connected clients.</param>
private void BroadcastMessage(Guid clientId, string message)
{
// Call each client's callback method
ThreadPool.QueueUserWorkItem
(
delegate
{
lock (clients)
{
List<Guid> disconnectedClientGuids = new List<Guid>();
foreach (KeyValuePair<Guid, IChatServiceCallback> client in clients)
{
try
{
client.Value.HandleMessage(message);
}
catch (Exception)
{
// TODO: Better to catch specific exception types.
// If a timeout exception occurred, it means that the server
// can't connect to the client. It might be because of a network
// error, or the client was closed prematurely due to an exception or
// and was unable to unregister from the server. In any case, we
// must remove the client from the list of clients.
// Another type of exception that might occur is that the communication
// object is aborted, or is closed.
// Mark the key for deletion. We will delete the client after the
// for-loop because using foreach construct makes the clients collection
// non-modifiable while in the loop.
disconnectedClientGuids.Add(client.Key);
}
}
foreach (Guid clientGuid in disconnectedClientGuids)
{
clients.Remove(clientGuid);
}
}
}
);
}
}
}
here is binding info
<service behaviorConfiguration="Services.ChatServiceBehavior" name="Services.ChatService">
<endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IChatService" contract="Services.IChatService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
here is two endpoint one for wsDualHttpBinding and another one for mex
so now my mex endpoint is
http://localhost:49722/ChatService.svc?wsdl
now i want to add another tcp endpoint and expose this service with two endpoint. so just tell me what i need to write for tcp endpoint and when i add tcp endpoint then what will mex endpoint for tcp because i want that user can create proxy with any of two url
one would be http url and another would be tcp url. so do i need to add mex for tcp here?
please guide me. thanks
you must start host manually
follow to msdn link http://msdn.microsoft.com/en-us/library/system.servicemodel.servicehost.aspx
edited
ServiceHost _serviceHost;
public void Start(Type type)
{
_serviceHost = new ServiceHost(type);
_serviceHost.Open();
}

Unable to get WCF services to run on shared server using IIS

I am unable to get WCF services to run on a shared server using IIS.
I have tried several tutorials:
http://technologyriver.blogspot.com/2012/02/prerequisites-check-windows-7.html
http://msdn.microsoft.com/en-us/library/ms733766.aspx
I've read blogs about executing command line instructions to enable WCF support on IIS.
However, the hosting company refuses to run the command on their box.
The services work fine on my dev machine.
However, I just cannot get the services to run on the remote server.
When clicking on an svc file I get the following error:
HTTP Error 404.3 - Not Found
The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.*
svc file:
<% #ServiceHost Language=C# Debug="true" Service="MyService" Factory="MyServiceHostFactory" CodeBehind="~/App_Code/Service.cs" %>
Web.config:
<service name="MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint contract="IMyService" binding="basicHttpBinding">
<identity>
<dns value="http://www.mydomain.com" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://www.mydomain.com:8732/Services/Service/" />
</baseAddresses>
</host>
</service>
Service.cs:
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
// A WCF service consists of a contract (defined below as IMyService, DataContract1),
// a class which implements that interface (see MyService),
// and configuration entries that specify behaviors associated with
// that implementation (see <system.serviceModel> in web.config)
[ServiceContract()]
public interface IMyService
{
[OperationContract]
string MyOperation1(string myValue1);
[OperationContract]
string MyOperation2(DataContract1 dataContractValue);
}
public class MyService : IMyService
{
public string MyOperation1(string myValue1)
{
return "Hello: " + myValue1;
}
public string MyOperation2(DataContract1 dataContractValue)
{
return "Hello: " + dataContractValue.FirstName;
}
}
[DataContract]
public class DataContract1
{
string firstName;
string lastName;
[DataMember]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
[DataMember]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
}
public class MyServiceHostFactory : ServiceHostFactoryBase
{
protected virtual ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
// Specify the exact URL of your web service
Uri webServiceAddress = new Uri("http://www.mydomain.com/MyService.svc");
MyServiceHost webServiceHost = new MyServiceHost(serviceType, webServiceAddress);
return webServiceHost;
}
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
throw new NotImplementedException();
}
}
public class MyServiceHost : ServiceHost
{
public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{ }
protected override void ApplyConfiguration()
{
base.ApplyConfiguration();
}
}
I had to switch hosts.
I was originally using DiscountASP.Net and they refused my request to ensure WCF settings were enabled and told me that I needed to hire a developer or follow the MS IIS specs.
(P.S. They didn't know that I'm actually an SDET.)
As a result, I had to switch to another provider (i.e. Winhost).
Things just work now without me having to do any crazy webconfig alterations or ServiceHostFactory coding crap that the previous host wanted me to do that had no success.
I spent 5 days reopening tickets with their tech support until I finally switched to a hosting company that actually supports WCF Services.
Thanks Winhost for ending this dreadful nightmare!
It seemed to be access/configurability problem on remote server then.
Try checking following areas for the deployed service.
Binding of the WCF service is configured correctly, DNS and port (default is 80)
Authentication Mode of service (Anonymous access should be allowed to browser through WSDL)
Permissions granted to the website (directory and user permissions)
If none of them work, then can you list down the steps you followed when service is deployed?

WCF Constructor with parameter / Custom Behavior Created In Code

I've a must to create wcf service with parameter.
I'm following this http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/8f18aed8-8e34-48ea-b8be-6c29ac3b4f41
First this is that I don't know how can I set this custom behavior "MyServiceBehavior" in my Web.config in ASP.NET MVC app that will host it.
As far as I know behaviors must be declared in section in wcf.config.
How can I add reference there to my behavior class from service assembly?
An second thing is that in the following example they have created local host (they use
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
to host in console application), but how I can add headers
OperationContext.Current.OutgoingMessageHeaders.Add ...
used to initialize constructor when I use in my WPF client application service reference and it will already create instance of web service "client" class
PBSDataCacheSyncContractClient client = new PBSDataCacheSyncContractClient();
is't it too late? Or when I have my own custom behavior can I do something like this:
PBSDataCacheSyncContractClient client = new PBSDataCacheSyncContractClient(my var for service constructor) ?
Regards,
Daniel Skowroński
EDIT: 31-05-2010
#manunt
I've improved my second question.
For answer to my first question, I've managed to create custom extenstion but I can't register it.
My scenario:
I have definitions for my web service in WCF library (interface, contract, implementation of IInstanceProvider, BehaviorExtensionElement)
then I reference it to another project ASP.NET application
inside ASP.NET application I have WCF service file and it is pointed to my class from WCF library
all my configuration is declared in web.config
In my WCF library I have:
namespace PBS.SyncService
{
using System;
using System.Data;
using System.Collections.ObjectModel;
using System.ServiceModel;
using Microsoft.Synchronization.Data;
using System.ServiceModel.Activation;
using Microsoft.Synchronization.Data.Server;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Configuration;
[XmlSerializerFormat()]
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public partial class PBSDataCacheSyncService : object, IPBSDataCacheSyncContract
{
private PBSDataCacheServerSyncProvider _serverSyncProvider;
public PBSDataCacheSyncService()
{
this._serverSyncProvider = new PBSDataCacheServerSyncProvider();
}
public PBSDataCacheSyncService(long doctorId)
{
this._serverSyncProvider = new PBSDataCacheServerSyncProvider();
this._serverSyncProvider.DoctorId = doctorId;
this._serverSyncProvider.InitializeCustomSyncProvider();
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public virtual SyncContext ApplyChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, DataSet dataSet, Microsoft.Synchronization.Data.SyncSession syncSession)
{
return this._serverSyncProvider.ApplyChanges(groupMetadata, dataSet, syncSession);
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public virtual SyncContext GetChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, Microsoft.Synchronization.Data.SyncSession syncSession)
{
return this._serverSyncProvider.GetChanges(groupMetadata, syncSession);
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public virtual SyncSchema GetSchema(Collection<string> tableNames, Microsoft.Synchronization.Data.SyncSession syncSession)
{
return this._serverSyncProvider.GetSchema(tableNames, syncSession);
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public virtual SyncServerInfo GetServerInfo(Microsoft.Synchronization.Data.SyncSession syncSession)
{
return this._serverSyncProvider.GetServerInfo(syncSession);
}
public bool InitializeCustomSyncProvider(long doctorId)
{
this._serverSyncProvider.DoctorId = doctorId;
return this._serverSyncProvider.InitializeCustomSyncProvider();
}
}
[XmlSerializerFormat()]
[ServiceContractAttribute()]
public interface IPBSDataCacheSyncContract
{
[OperationContract()]
SyncContext ApplyChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, DataSet dataSet, Microsoft.Synchronization.Data.SyncSession syncSession);
[OperationContract()]
SyncContext GetChanges(Microsoft.Synchronization.Data.SyncGroupMetadata groupMetadata, Microsoft.Synchronization.Data.SyncSession syncSession);
[OperationContract()]
SyncSchema GetSchema(Collection<string> tableNames, Microsoft.Synchronization.Data.SyncSession syncSession);
[OperationContract()]
SyncServerInfo GetServerInfo(Microsoft.Synchronization.Data.SyncSession syncSession);
[OperationContract()]
bool InitializeCustomSyncProvider(long doctorId);
[OperationContract()]
string[] GetSyncAdapterInfo();
}
public class PBSDataCacheSyncProvider : IInstanceProvider
{
public object GetInstance(InstanceContext instanceContext, Message message)
{
string doctorId = message.Headers.GetHeader<string>("DoctorId", "http://***/SyncService.svc");
if (doctorId != null)
{
return new PBSDataCacheSyncService(Convert.ToInt64(doctorId));
}
else
{
return new PBSDataCacheSyncService();
}
}
public object GetInstance(InstanceContext instanceContext)
{
return new PBSDataCacheSyncService();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
public class PBSDataCacheSyncBehavior : BehaviorExtensionElement, IServiceBehavior
{
PBSDataCacheSyncProvider pbsProvider = new PBSDataCacheSyncProvider();
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = this.pbsProvider;
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
public override Type BehaviorType
{
get { return typeof(PBSDataCacheSyncBehavior); }
}
protected override object CreateBehavior()
{
return new PBSDataCacheSyncBehavior();
}
}
}
My WCF Service file has name: SyncService.svc and in my makrup I have:
<%# ServiceHost Language="C#" Debug="true" Service="PBS.SyncService.PBSDataCacheSyncService" CodeBehind="PBS.SyncService.PBSDataCache.Server.SyncContract.cs" %>
My web.config:
<service name="PBS.Web.SyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior">
<host>
<baseAddresses>
<add baseAddress="http://***/SyncService.svc" />
</baseAddresses>
</host>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="" binding="basicHttpBinding" contract="PBS.SyncService.IPBSDataCacheSyncContract" />
</service>
<serviceBehaviors>
<behavior name="behPBSDataCacheSyncBehavior">
<PBSDataCacheSyncBehavior /> <!-- this element is being ignored -->
</behavior>
</serviceBehaviors>
<extensions>
<behaviorExtensions>
<add name="PBSDataCacheSyncBehavior" type="PBS.SyncService.PBSDataCacheSyncBehavior, PBS.SyncService,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
Can you tell me what I'm missing in this point?
Why parser ignores my custom extension declaration?
I have following error:
Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
Parser Error Message: An error occurred creating the configuration section handler for system.serviceModel/behaviors: Extension element 'PBSDataCacheSyncBehavior' cannot be added to this element. Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions.
Parameter name: element
EDIT: 01-06-2010
Problem with parser resolved by typing all the declaration in one single line.
I still don't know how to add header when I have service reference.
In my WPF application I have only client instance witch implements my IPBSDataCacheSyncContract autogenerated by Service Reference.
And when I initialize it it only has constructors:
public PBSDataCacheSyncContractClient() {
}
public PBSDataCacheSyncContractClient(string endpointConfigurationName) :
base(endpointConfigurationName) {
}
public PBSDataCacheSyncContractClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public PBSDataCacheSyncContractClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public PBSDataCacheSyncContractClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress) {
}
Where I can add headers?
"As for the second question - you should define message contract with needed headers in it and provide header values for each message separately." Could you be more specific?
EDIT: 02-06-2010
I've encountered other issue.
When I have now my configuration httpGetEnabled is ignored... :
<serviceBehaviors>
<behavior name="behPBSDataCacheSyncBehavior">
<PBSDataCacheSyncBehavior />
<serviceMetadata httpGetEnabled="true" /><!-- ignored -->
<serviceDebug includeExceptionDetailInFaults="true" /><!-- ignored -->
</behavior>
</serviceBehaviors>
How can I fix it?
EDIT: 02-06-2010
OK I've figured workaround. Still it is weird but it works!
My problem was with web.config. And none name behavior entry entry is recognized by my service and not any other... So I simply added no name behavior to collection.
<serviceBehaviors>
<behavior name="">
<PBSDataCacheSyncBehavior />
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="behPBSDataCacheSyncBehavior">
<PBSDataCacheSyncBehavior />
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
And I add header in my code this way:
int doctorId = 2;
Sync.PBSDataCacheSyncContractClient client = new Sync.PBSDataCacheSyncContractClient();
new OperationContextScope (client.InnerChannel);
OperationContext.Current.OutgoingMessageHeaders.Add(
MessageHeader.CreateHeader("DoctorId", "http://***/SyncService.svc", doctorId));
I've changed topic to be more useful.
HTH
Regards,
Daniel Skowroński
I know what the problem is with the behavior not being found and why you need the hack with the behavior with no name.
If you look at this line in your svc markup file:
<%# ServiceHost Language="C#" Debug="true" Service="PBS.SyncService.PBSDataCacheSyncService" CodeBehind="PBS.SyncService.PBSDataCache.Server.SyncContract.cs" %>
and this line in your web.Config:
<service name="PBS.Web.SyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior">
You will notice that the name specified in the service tag is different from the Service class specified in the Service attribute in the markup file.
I think it should be something like this:
instead of
<service name="PBS.Web.SyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior">
this
<service name="PBS.SyncService.PBSDataCacheSyncService" behaviorConfiguration="behPBSDataCacheSyncBehavior">
These two values I think have to the same not sure but in my case the two values were different and I had to do the blank service name hack. But by setting both values the same, it worked. It found the behavior without needing the blank one and I was able to access my wsdl.
Answer for the first question you can find here.
Regarding error you are getting - do not split definition of your extension into two lines, because xml parser cannot handle that.
A sample how to define custom headers without specifying message contract:
var client = new Service1Client();
new OperationContextScope(client.InnerChannel);
MessageHeader<string> typedHeader = new MessageHeader<string>("headercontent");
MessageHeader header = typedHeader.GetUntypedHeader("myheader", "myns");
OperationContext.Current.OutgoingMessageHeaders.Add(header);