WCF Custom Validator - wcf

While setting up a CustomValidator I'm getting the following error:
Could not load file or assembly 'Ringo.Authentication' or one of its dependencies. The system cannot find the file specified.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using Ringo.Utilities;
namespace Ringo.Authentication
{
public class CustomUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string Username, string Password)
{
Accounts account = new Accounts();
if (account.CheckUserAccount(Username, Password))
{
return;
}
throw new SecurityTokenException("Accout is Invalid");
}
}
}
<serviceCredentials >
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Ringo.Authentication.CustomUserNameValidator, Ringo.Authentication"/>
</serviceCredentials>
Any help would be great thanks!

The Following:
<serviceCredentials >
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Ringo.Authentication.CustomUserNameValidator, **Ringo.Authentication**"/>
</serviceCredentials>
Should Be:
<serviceCredentials >
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Ringo.Authentication.CustomUserNameValidator, **Ringo**"/>
</serviceCredentials>

Related

WCF - Injecting into a Custom UserNamePasswordValidator with MEF

I have a WCF Service which is using DI via MEF. That part is working fine.
I also have a Custom UserNamePasswordValidator which works as long as I use a parameterless constructor and 'new' everything up. However I would like to introduce MEF into that as well.
The service is hosted in IIS so I have to intercept it somewhat to get MEF to work as it is.
I've provided cross sections of my code below and any help would be appreciated!
Here is my web.config: -
<behavior name="StandardServiceBehaviour">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType=
"WebService.Validators.CustomUserNamePasswordValidator, WebService" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<dataContractSerializer maxItemsInObjectGraph="67108864" />
</behavior>
My custom validator is as follows: -
[Export(typeof(ICustomUserNamePasswordValidator))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class CustomUserNamePasswordValidator : UserNamePasswordValidator, ICustomUserNamePasswordValidator
{
[ImportingConstructor]
public CustomUserNamePasswordValidator([NotNull] IConnectionProvider connectionProvider)
{
}
.....
}
I'm using a custom attribute on my Web Service called WebServiceExport, which subclasses the MEF Export attribute and includes an InstanceProvider: -
[WebServiceExport(typeof(IGeneralService))]
public class GeneralService : IGeneralService
{
....
}
Here is the Export Attribute: -
public class WebServiceExportAttribute : ExportAttribute, IContractBehavior, IContractBehaviorAttribute
{
public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)
{
var contractType = description.ContractType;
dispatch.InstanceProvider = new MefInstanceProvider(contractType);
}
....
}
And finally here is the Instance Provider: -
public class MefInstanceProvider : IInstanceProvider
{
public MefInstanceProvider(Type serviceContract)
{
_serviceContract = serviceContract;
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
BuildInstance(); //compose MEF parts
}
....
}

Need help on WCF Design

I have a project written in C++ COM+(Server Side) and VB6(Client Side). We have decided to redesign the project in WCF Architecture using C# language.
As a part of my learning, I have created a simple test Project in WCF which is below.
The idea is that when the WBWindowsService is started, it should create a TASWB object and then Run a Thread to Calculate the Weight. So when a client call the Getweight() method, it should be able to receive the weight calculated by the thread.
But when I tried, I am always getting 0 which is the initial value. So I think what i am missing is how to manage the objects in WCF.
Kindly Help. Thanks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration;
using System.Configuration.Install;
namespace TASWeighBridge
{
public class WBWindowsService : ServiceBase
{
public ServiceHost serviceHost = null;
private TASWB obj;
public WBWindowsService()
{
// Name the Windows Service
ServiceName = "WBWindowsService";
}
public static void Main()
{
ServiceBase.Run(new WBWindowsService());
}
// Start the Windows service.
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
obj = new TASWB();
obj.RunThread();
// Create a ServiceHost for the CalculatorService type and
// provide the base address.
serviceHost = new ServiceHost(typeof(TASWB));
// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
}
protected override void OnStop()
{
if (serviceHost != null)
{
serviceHost.Close();
serviceHost = null;
}
}
}
}
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration;
using System.Configuration.Install;
namespace TASWeighBridge
{
// Define a service contract.
[ServiceContract]
public interface IWeighBridge
{
[OperationContract]
double Getweight();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration;
using System.Configuration.Install;
using System.Threading;
namespace TASWeighBridge
{
// Implement the ICalculator service contract in a service class.
public class TASWB : IWeighBridge
{
private double weight = 0;
public void RunThread()
{
Thread T1 = new Thread(new ThreadStart(CalcWeight));
T1.Start();
//T1.Join();
}
private void CalcWeight()
{
Thread.Sleep(1000);
weight = weight + 1;
}
public double Getweight()
{
return weight;
}
}
}
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="TASWeighBridge.TASWB"
behaviorConfiguration="TASWBBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/TASWBService"/>
</baseAddresses>
</host>
<!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/TASWBService -->
<endpoint address=""
binding="wsHttpBinding"
contract="TASWeighBridge.IWeighBridge" />
<!-- the mex endpoint is exposed at http://localhost:8000/TASWBService/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="TASWBBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

My WCF Implementation class reference is not showing up in Windows Service

My Windows Service is now showing up my WCF Implementation class.
Hence when I start my service it is giving me error of "ServiceHost only supports class service types."
Here's my code:
try
{
Console.WriteLine("Testing 1");
WCFEmailEventLog.WriteEntry("My service started");
System.Diagnostics.Debugger.Break();
// Create a ServiceHost
// provide the base address.
serviceHost = new ServiceHost(typeof(TestBulkEmailService.BulkEmailService), new Uri("http://localhost/TestBulkEmailService/TestBulkEmailService.svc") );
WCFEmailEventLog.WriteEntry("After Service host ");
// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
In the above code the typeOf(TestBulkEmailService.BulkEmailService) does not show the Implementation class BulkEmailService and only shows my WCF Contract IBulkEmailService.
What am I doing wrong?
Here is my app.config file:
<services>
<service name="WW.Common.Service.Impl.BulkEmailService" behaviorConfiguration="BulkEmailService">
<host>
<baseAddresses>
<add baseAddress="http://localhost/TestBulkEmailService/TestBulkEmailService.svc"/>
</baseAddresses>
</host>
<endpoint address="BulkEmailService" binding="basicHttpBinding" contract="TestBulkEmailService.IBulkEmailService" />
<endpoint address="mex" binding="basicHttpBinding" name="mexEndpoint" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="BulkEmailService">
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true" />
<serviceSecurityAudit auditLogLocation="Application"
suppressAuditFailure="true"
serviceAuthorizationAuditLevel="Success"
messageAuthenticationAuditLevel="Success" />
</behavior>
</serviceBehaviors>
</behaviors>
And here is my .svc file which has been hosted in IIS and is running fine when using a client app.
<%# ServiceHost Language="C#" Debug="true" Service="WW.Common.Service.Impl.BulkEmailService" %>
Here's my Implementation and Contract for the WCF Service which I have used as Service reference and have named it as TestBulkEmailService.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using WW.EnterpriseLibrary.Error;
using WW.Common.Service.Contract;
using WW.Common.Data.DTO;
using WW.Common.Data;
using WW.ServiceCore.Error;
using WW.ServiceCore.Log;
using BulkEmailDac = WW.Common.DataAccess.Impl.BulkEmailDac;
namespace WW.Common.Service.Impl
{
public class BulkEmailService : IBulkEmailService
{
private BulkEmailDac emailDac;
ErrorMsg err_msg = new ErrorMsg();
public BulkEmailService()
{
emailDac = new BulkEmailDac();
}
public string Abc(string s1)
{
string result = s1;
return result;
}
/// <summary>
/// Get Bulk Email Record List
/// </summary>
/// <returns></returns>
public BulkEmailDTOList GetBulkEmailInfo(int recordLimit)
{
try
{
return emailDac.GetBulkEmailInfo(recordLimit);
}
catch (Exception ex)
{
if (ex is FaultException<OperationFault>)
{
//throw;
Console.WriteLine("faultException1 Message: " + ex.Message);
throw;
}
else
{
//LOG AND THROW AN UNKNOWN EXCEPTION
ApplicationLog.WriteError(DateTime.Now.ToString() + "|"
+ "GetBulkEmailInfo" + "|"
+ ex.Message + "|"
+ ex.StackTrace);
Console.WriteLine("faultException2 Message: " + ex.StackTrace);
throw new FaultException<OperationFault>(new OperationFault(ex.Message, ErrorMessages.Unknown_Error_Code));
}
}
}
Contract:
using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using WW.EnterpriseLibrary.Error;
using WW.Common.Data.DTO;
namespace WW.Common.Service.Contract
{
[ServiceContract]
public interface IBulkEmailService
{
[OperationContract]
[FaultContractAttribute(typeof(OperationFault))]
BulkEmailDTOList GetBulkEmailInfo(int recordLimit);
[OperationContract]
[FaultContractAttribute(typeof(OperationFault))]
int SendBulkEmail(string emailFm, string emailTo, string ccTo, string subject, string body);
}

405 method not allowed using [webHttpBinding]

I'm getting problems with jquery call wcf. I've already search and found some solutions but it still raise me an error "405 method not allowed". Below is may code
-Interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.ServiceModel;
namespace WcfServiceLibrary
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IContactService" in both code and config file together.
[ServiceContract]
public interface IContactService
{
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Contact GetContactInfo();
}
}
My service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.ServiceModel;
namespace WcfServiceLibrary
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ContactService" in both code and config file together.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ContactService : IContactService
{
public Contact GetContactInfo()
{
ContactBL contactBL = new ContactBL();
return contactBL.GetContact();
}
}
}
My object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime;
using System.Runtime.Serialization;
namespace WcfServiceLibrary
{
[DataContract]
public class Contact
{
[DataMember]
public int Id {get;set;}
[DataMember]
public string Fullname {get; set;}
[DataMember]
public string email { get; set; }
}
}
BL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WcfServiceLibrary
{
class ContactBL
{
public ContactBL() { }
public Contact GetContact()
{
return new Contact {email="thang.nguyen#saas.com.vn", Fullname="NVTThang",Id=2 };
}
}
}
And also my WCF configuration:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="myBehavior" name="WcfServiceLibrary.ContactService">
<endpoint address="ajaxEp" behaviorConfiguration="epAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="webBinding" name="epWebHttp"
contract="WcfServiceLibrary.IContactService" />
<endpoint address="mex" binding="mexHttpBinding" name="epMex"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="epAjaxBehavior">
<webHttp />
<enableWebScript/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="myBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://localhost"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
The I deploy my wcf on IIS 7.5 then I created a web client using jquery ajax call to my service.
$.ajax({
type: "GET",
url: "http://localhost/WcfTestService/Service.svc/ajaxEp/GetContactInfo",
data: '',
contentType: "application/json;charset=utf-8",
dataType: "json",
processdata: true,
success: function (msg) {
alert(msg);
//ServiceSucceeded(msg);
},
error: ServiceFailed
});
function ServiceFailed(err){
alert(err.responseText);
return;
}
when I call my service it always raises me "405 Method Not Allowed" and I've tried aspnet_regiis -i and ServiceModelReg -i but it didn't effect. Please suggest me any solutions.
Thanks in advance!
I can see a few problems in your service:
For "GET" requests, you should use WebGet, instead of WebInvoke, on your contract:
[ServiceContract]
public interface IContactService
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Contact GetContactInfo();
}
In your endpoint behavior you have 2 behaviors for scripting: webHttp and enableWebScript. You only need the former. The latter is for integration with ASP.NET AJAX specifically.
<endpointBehaviors>
<behavior name="epAjaxBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
This probably isn't causing any issues, but in the $.ajax call, you don't need to specify a content-type, since it's a GET request (so there's no content). Also, since you aren't passing any parameter, you also don't need the data parameter.
$.ajax({
type: "GET",
url: "http://localhost/WcfTestService/Service.svc/ajaxEp/GetContactInfo",
dataType: "json",
success: function (msg) {
alert(msg);
//ServiceSucceeded(msg);
},
error: ServiceFailed
});
Try this in your service:
[ScriptMethod]
public Contact GetContact(...)

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);