Imagine I want to call a external (meaning I have no control over the contract) REST service using WCF.
I have the following contract
[ServiceContract]
public interface ISomeRestApi
{
[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "blablabla/{parameter1}/{parameter2}")]
void PutSomething(string parameter1, string parameter2);
}
Say that one of my parameters is a forward slash (/)
public class Test{
[Fact]
public void TestPutSomething()
{
ISomeRestApi api = CreateApi();
//this results in the url: http://server/blablabla///someotherparam
api.PutSomething("/", "someotherparam");
//this also results in the url: http://server/blablabla///someotherparam
api.PutSomething(HttpUtility.UrlEncode("/"), "someotherparam");
//but i want: http://server/blablabla/%2F/someotherparam
}
}
How do I force WCF to UrlEncode my UriTemplate path parameter?
With lots of trial and error I found a very ugly and totally illogic solution to my problem. But still... Maybe this post can help someone in the future.
Note that this "solution" works for me in .NET 4.5. I do not guarantee it'll work for you.
The problem comes down to this:
it's impossible (AFAIK) to put a escaped forward slash in a Uri in .NET
for communicating with an external service (RabbitMQ) I really need to be able put %2f (i.e. forward slash) in my request Url
The following post put me in the "right" direction: How to stop System.Uri un-escaping forward slash characters
I tried the solution proposed in the post, but... to no avail
Then after lots of cursing, googling, reverse engineering and so forth i came up with the following piece of code:
/// <summary>
/// Client enpoint behavior that enables the use of a escaped forward slash between 2 forward slashes in a url
/// </summary>
public class EncodeForwardSlashBehavior:IEndpointBehavior
{
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ForwardSlashUrlInspector());
}
}
/// <summary>
/// Inspector that modifies a an Url replacing /// with /%2f/
/// </summary>
public class ForwardSlashUrlInspector:IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
string uriString = request.Headers.To.ToString().Replace("///", "/%2f/");
request.Headers.To = new Uri(uriString);
AddAllowAnyOtherHostFlagToHttpUriParser();
return null;
}
/// <summary>
/// This is one of the weirdest hacks I ever had to do, so no guarantees can be given to this working all possible scenarios
/// What this does is, it adds the AllowAnyOtherHost flag to the private field m_Flag on the UriParser for the http scheme.
/// Replacing /// with /%2f/ in the request.Headers.To uri BEFORE calling this method will make sure %2f remains unescaped in your Uri
/// Why does this work, I don't know!
/// </summary>
private void AddAllowAnyOtherHostFlagToHttpUriParser()
{
var getSyntaxMethod =
typeof(UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
if (getSyntaxMethod == null)
{
throw new MissingMethodException("UriParser", "GetSyntax");
}
var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
var flagsField =
uriParser.GetType().BaseType.GetField("m_Flags", BindingFlags.Instance|BindingFlags.NonPublic);
if (flagsField == null)
{
throw new MissingFieldException("UriParser", "m_Flags");
}
int oldValue = (int)flagsField.GetValue(uriParser);
oldValue += 4096;
flagsField.SetValue(uriParser, oldValue);
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
So basically I'm creating a custom EndpointBehavior that uses reflection to add an enum flag to a private variable inside the UriParser. This apparently prevents the escaped forward slash in my request.Headers.To uri from being unescaped.
Related
Leaving a SOAP field element empty results in a cast error for native types. (sadly cannot use xsi:nil="true" due to client constraints)
Marking the WCF contract native type as nullable<> does not appear to be enough to stop the following error being returned to the client.
The string '' is not a valid Boolean value.
at System.Xml.XmlConvert.ToBoolean(String s)
at System.Xml.XmlConverter.ToBoolean(String value)
System.FormatException
does anyone know the best method of instructing the DataContractSerializer to convert empty elements to be deserialized to null?
My example WCF service contract;
[ServiceContract()]
public interface IMyTest
{
[OperationContract]
string TestOperation(TestRequest request);
}
[ServiceBehavior()]
public class Settings : IMyTest
{
public string TestOperation(TestRequest request)
{
if (request.TestDetail.TestBool.HasValue)
return "Bool was specified";
else
return "Bool was null";
}
}
[DataContract()]
public class TestRequest
{
[DataMember(IsRequired = true)]
public int ID { get; set; }
[DataMember(IsRequired = true)]
public TestDetail TestDetail { get; set; }
}
[DataContract()]
public class TestDetail
{
[DataMember()]
public bool? TestBool { get; set; }
}
How can we get WCF to accept the following submission;
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ster="mynamespace">
<soapenv:Header/>
<soapenv:Body>
<ster:TestOperation>
<ster:request>
<ster:ID>1</ster:ID>
<ster:TestDetail>
<ster:TestBool></ster:TestBool>
</ster:TestDetail>
</ster:request>
</ster:TestOperation>
</soapenv:Body>
</soapenv:Envelope>
The client is only able to change the value it inserts <ster:TestBool>{here}</ster:TestBool> so true false or nothing are the only options.
Ok I believe I have cracked this by using an Operation Behavior to modify the underlying message before its formatted via IDispatchMessageFormatter.
The following code provides a solution against a service that is based on WCF file-less activation.
I wanted to have my IOperationBehavior live in the form of a Attribute class. Then I could simply decorate each Service Operation with my new attribute which would instigate the IOperationBehavior for that Operation - very nice and simple for the end user.
The key problem is where you apply the behavior, this is critical. The order of the operation behaviors that are called by WCF when applying the behavior via an attribute are different to when applying at the service host. The attribute based order is as follows:
System.ServiceModel.Dispatcher.OperationInvokerBehavior
MyOperationBehaviorAttribute
System.ServiceModel.OperationBehaviorAttribute
System.ServiceModel.Description.DataContractSerializerOperationBehavior
System.ServiceModel.Description.DataContractSerializerOperationGenerator
For some reason an operation behavior (only when applied via the use of an attribute) will be called before the DataContractSerializerOperationBehavior. This is a problem because in my behavior I want to delegate deserialization to the DataContractSerializerOperationBehavior Formatter (passed into my behavior as the inner formatter) within my formatter, after I have adjusted the message (see code). I don't want to have to re-write a deserialization routine when Microsoft provided a perfectly good deserializer already. I merely correct the XML in the first instance so that blanks are converted to nulls which are correctly represented within the XML so that the DataContractSerializer can tie them up to nullable types in the service interface.
So this means we cannot use attribute-based behaviors as they were intended since WCF may well be broken in a rather subtle way here since I can see no reason for this phenomenon. So we can still add an IOperationBehavior to an operation, we just have to manually assign it at the service host creation stage, because then our IOperationBehavior is inserted into the 'correct' sequence, that is, after the DataContractSerializerOperationBehavior has been created, only then can I get a reference to the inner formatter.
// This operation behaviour changes the formatter for a specific set of operations in a web service.
[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = false)]
public class NullifyEmptyElementsAttribute : Attribute
{
// just a marker, does nothing
}
public class NullifyEmptyElementsBahavior : IOperationBehavior
{
#region IOperationBehavior Members
public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { }
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
// we are the server, we need to accept client message that omit the xsi:nill on empty elements
dispatchOperation.Formatter = new NullifyEmptyElementsFormatter(dispatchOperation.Formatter);
}
public void Validate(OperationDescription operationDescription) { }
#endregion IOperationBehavior Members
}
/// <summary>
/// This customized formatter intercepts the deserialization process to perform extra processing.
/// </summary>
public class NullifyEmptyElementsFormatter : IDispatchMessageFormatter
{
// Hold on to the original formatter so we can use it to return values for method calls we don't need.
private IDispatchMessageFormatter _innerFormatter;
public NullifyEmptyElementsFormatter(IDispatchMessageFormatter innerFormatter)
{
// Save the original formatter
_innerFormatter = innerFormatter;
}
/// <summary>
/// Check each node and add the xsi{namespace}:nil declaration if the inner text is blank
/// </summary>
public static void MakeNillable(XElement element)
{
XName _nillableAttributeName = "{http://www.w3.org/2001/XMLSchema-instance}nil"; // don't worry, the namespace is what matters, not the alias, it will work
if (!element.HasElements) // only end nodes
{
var hasNillableAttribute = element.Attribute(_nillableAttributeName) != null;
if (string.IsNullOrEmpty(element.Value))
{
if (!hasNillableAttribute)
element.Add(new XAttribute(_nillableAttributeName, true));
}
else
{
if (hasNillableAttribute)
element.Attribute(_nillableAttributeName).Remove();
}
}
}
public void DeserializeRequest(System.ServiceModel.Channels.Message message, object[] parameters)
{
var buffer = message.CreateBufferedCopy(int.MaxValue);
var messageSource = buffer.CreateMessage(); // don't affect the underlying stream
XDocument doc = null;
using (var messageReader = messageSource.GetReaderAtBodyContents())
{
doc = XDocument.Parse(messageReader.ReadOuterXml()); // few issues with encoding here (strange bytes at start of string), this technique resolves that
}
foreach (var element in doc.Descendants())
{
MakeNillable(element);
}
// create a new message with our corrected XML
var messageTarget = Message.CreateMessage(messageSource.Version, null, doc.CreateReader());
messageTarget.Headers.CopyHeadersFrom(messageSource.Headers);
// now delegate the work to the inner formatter against our modified message, its the parameters were after
_innerFormatter.DeserializeRequest(messageTarget, parameters);
}
public System.ServiceModel.Channels.Message SerializeReply(System.ServiceModel.Channels.MessageVersion messageVersion, object[] parameters, object result)
{
// Just delegate this to the inner formatter, we don't want to do anything with this.
return _innerFormatter.SerializeReply(messageVersion, parameters, result);
}
}
public class MyServiceHost : ServiceHost
{
public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses) { }
protected override void OnOpening()
{
base.OnOpening();
foreach (var endpoint in this.Description.Endpoints)
{
foreach (var operation in endpoint.Contract.Operations)
{
if ((operation.BeginMethod != null && operation.BeginMethod.GetCustomAttributes(_NullifyEmptyElementsBahaviorAttributeType, false).Length > 0)
||
(operation.SyncMethod != null && operation.SyncMethod.GetCustomAttributes(_NullifyEmptyElementsBahaviorAttributeType, false).Length > 0)
||
(operation.EndMethod != null && operation.EndMethod.GetCustomAttributes(_NullifyEmptyElementsBahaviorAttributeType, false).Length > 0))
{
operation.Behaviors.Add(new NullifyEmptyElementsBahavior());
}
}
}
}
}
Perhaps since I am only modifying the incoming message, I could instead use IDispatchMessageInspector which will remove the dependency on the IDispatchMessageFormatter activation order. But this works for now ;)
Usage:
Add to your operation
[ServiceContract(Namespace = Namespaces.MyNamespace)]
public interface IMyServiceContrct
{
[OperationContract]
[NullifyEmptyElements]
void MyDoSomthingMethod(string someIneteger);
}
Tie into your service
A. if you have .svc simply reference MyServiceHost
<%# ServiceHost
Language="C#"
Debug="true"
Service="MyNameSpace.MyService"
Factory="MyNameSpace.MyServiceHost" %>
B. if your using file-less activation services, add this to your web.config file
<system.serviceModel>
... stuff
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" >
<!-- WCF File-less service activation - there is no need to use .svc files anymore, WAS in IIS7 creates a host dynamically - less config needed-->
<serviceActivations >
<!-- Full access to Internal services -->
<add relativeAddress="MyService.svc"
service="MyNameSpace.MyService"
factory="MyNameSpace.MyServiceHost" />
</serviceActivations>
</serviceHostingEnvironment>
... stuff
</system.serviceModel>
I have a WCF service configured and I'm using routing to configure it. Everything is working the way I want it, except the 404 messages have a body stating Service Endpoint not found.
I'd like the 404 to have an empty response body.
Here is my route registration:
public class Global : HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
private void RegisterRoutes(RouteCollection routes)
{
routes.Add(new ServiceRoute("RootService", new WebServiceHostFactory(), typeof(ServiceProvider)));
}
Here is my service class:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceContract]
public class ServiceProvider
{
[WebGet]
public Test ValidUrl()
{
return new Test();
}
}
How do I make the response for this url http://localhost/RootService have an empty 404 body?
I found a few ways to do this and I've listed two below. They key is having the UriTemplate set as *. This makes the method match all routes that aren't explicitly matched otherwise.
[WebGet(UriTemplate="*")]
public void ErrorForGet()
{
throw new WebFaultException(HttpStatusCode.NotFound);
}
I don't like this way as well, but it works:
[WebGet(UriTemplate="*")]
public void ErrorForGet()
{
WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound();
}
Both of these methods have overloads that take a string as a message to provide to the requesting client. The WebFaultException needs to be like this going that route though: throw new WebFaultException<string>("Resource not found", HttpStatusCode.NotFound);
I have a WCF Service callable in SOAP and REST.
If a make SOAP call this works properly, but with REST I have problems.
In summary, the method return POCO ENTITY, but when I call I get a connection error canceled.
The same thing not happens if I call another method that returns a boolean or a string (ie native types).
The error seemed to me that POCO entity that I'm using was not really (that's what I'm using Devart so pretty sure it is).
So what I did, I created a custom map of it (with same property) and i have used AutoMapper to do mapping.
The problem is still there :-(
This is the .svc.cs
public List<GetLuoghiSimiliByAddressesDTO> GetLuoghiSimiliByAddress(string toponimo, string nomestrada, string civico, int idcomune)
{
Agile.SL.Services.IAnagraficaService srv = new Agile.SL.Services.Impl.AnagraficaService();
List<GetLuoghiSimiliByAddressesDTO> result = new List<GetLuoghiSimiliByAddressesDTO>();
Mapper.CreateMap<DTOGetLuoghiSimiliByAddress, GetLuoghiSimiliByAddressesDTO>();
foreach (var dto in srv.GetLuoghiSimiliByAddress(toponimo, nomestrada, civico, idcomune).ToList<DTOGetLuoghiSimiliByAddress>())
{
GetLuoghiSimiliByAddressesDTO newdto = Mapper.Map<DTOGetLuoghiSimiliByAddress, GetLuoghiSimiliByAddressesDTO>(dto);
result.Add(newdto);
}
return result;
}
result contains properly my list of objects.
This is svc
[OperationContract]
[WebGet(UriTemplate = "GetLuoghiSimiliByAddress?Toponimo={toponimo}&Nome_Strada={nomestrada}&Civico={civico}&Id_Comune={idcomune}",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
List<GetLuoghiSimiliByAddressesDTO> GetLuoghiSimiliByAddress(string toponimo, string nomestrada, string civico, int idcomune);
Work properly with this method and operation contract
public bool IsUserAlreadyRegistered(string email)
{
Agile.SL.Services.IAnagraficaService srv = new Agile.SL.Services.Impl.AnagraficaService();
return srv.CheckEmailExistance(email);
}
[OperationContract]
[WebGet(UriTemplate = "IsUserAlreadyRegistered?Email={email}",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
bool IsUserAlreadyRegistered(string email);
this is GetLuoghiSimiliByAddressesDTO
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
namespace Merqurio.Agile.DL.Model.Entities
{
[DataContract(IsReference = true)]
[Serializable]
public class GetLuoghiSimiliByAddressesDTO
{
private int _Id_Luogo;
private string _Toponimo;
private string _Nome_Strada;
private string _Civico;
public GetLuoghiSimiliByAddressesDTO()
{
}
/// <summary>
/// There are no comments for Id_Luogo in the schema.
/// </summary>
[DataMember(Order=1)]
public int Id_Luogo
{
get
{
return this._Id_Luogo;
}
set
{
if (this._Id_Luogo != value)
{
this._Id_Luogo = value;
}
}
}
/// <summary>
/// There are no comments for Toponimo in the schema.
/// </summary>
[DataMember(Order=2)]
public string Toponimo
{
get
{
return this._Toponimo;
}
set
{
if (this._Toponimo != value)
{
this._Toponimo = value;
}
}
}
/// <summary>
/// There are no comments for Nome_Strada in the schema.
/// </summary>
[DataMember(Order=3)]
public string Nome_Strada
{
get
{
return this._Nome_Strada;
}
set
{
if (this._Nome_Strada != value)
{
this._Nome_Strada = value;
}
}
}
/// <summary>
/// There are no comments for Civico in the schema.
/// </summary>
[DataMember(Order=4)]
public string Civico
{
get
{
return this._Civico;
}
set
{
if (this._Civico != value)
{
this._Civico = value;
}
}
}
}
}
Please help me!
You can't use "IsReference = true" on your DataContract.
From MSDN :
Use the IsReference property to instruct the DataContractSerializer to
insert XML constructs that preserve object reference information.
You are returning JSON, not XML...
Anyways you don't need it here, I don't see any circular dependency.
What is the error code you get back when you make the REST call. Also try to enable tracing on your service to see why the request fails via REST. To enable tracing follow this link
Also try to use fiddler to inspect your request that is being made to your service.
I have a service exposing 2 endpoint and I would like to apply message formatting to only one of the endpoints.
To do that I am looking to capture the endpoint name in order to apply the MessageFormatter only for this specific endpoint.
This is the code of my Operation behavior attribute:
public class JsonRpcMessageValidation : Attribute, IOperationBehavior
{
#region Properties
public Type serializeType { get; set; }
public Type deserializeType { get; set; }
#endregion
#region Constructors
/// <summary>
///
/// </summary>
/// <param name="serializeType">Serialize Type</param>
/// <param name="deserializeType">Deserialize Type</param>
public JsonRpcMessageValidation(Type serializeType, Type deserializeType)
{
this.serializeType = serializeType;
this.deserializeType = deserializeType;
}
#endregion
#region Methods
public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
{
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
JsonRpcRequestMessageInspector jrrmInspector = new JsonRpcRequestMessageInspector();
dispatchOperation.ParameterInspectors.Add(jrrmInspector);
JsonRpcMessageFormatter jrmFormatter = new JsonRpcMessageFormatter(serializeType, deserializeType);
dispatchOperation.Formatter = jrmFormatter;
}
public void Validate(OperationDescription operationDescription)
{
}
#endregion
}
I decorate the method in the interface with this attributes and I need the Type information in order to perform serialization and deserialization on the incoming and outcoming messages.
Does any know how to get the current endpoint information at this point in the code?
Thanks
I was able to work around that:
I simply used the method below to retrieve the endpoint from the dispatchOperation:
private static string GetCurrentEndpointName(System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
string endpoint = String.Empty;
if (dispatchOperation.Parent.EndpointDispatcher.EndpointAddress.Uri.Segments.Count() > 0)
{
endpoint = dispatchOperation.Parent.EndpointDispatcher.EndpointAddress.Uri.Segments[dispatchOperation.Parent.EndpointDispatcher.EndpointAddress.Uri.Segments.Count() - 1];
}
return endpoint;
}
And now it applies the Message Formatters EXCLUSIVELY to the endpoint "json" in the ApplyDispatchBehavior method:
public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
{
JsonRpcRequestMessageInspector jrrmInspector = new JsonRpcRequestMessageInspector();
dispatchOperation.ParameterInspectors.Add(jrrmInspector);
var endpoint = GetCurrentEndpointName(dispatchOperation);
//it only applies the Message Formatter to the 'json' endpoint
if (endpoint == "json")
{
JsonRpcMessageFormatter jrmFormatter = new JsonRpcMessageFormatter(serializeType, deserializeType);
dispatchOperation.Formatter = jrmFormatter;
}
}
I think it would be more suitable to use an IEndpointBehavior implementation, that you use on the appropriate endpoint where you want the custom MessageFormatter.
--larsw
Actually I need to use IOperationBehavior because I use the attribute to decorate the methods and each method have different request and response types that I use to perform serialization and deserialization on the incoming and outcoming messages otherwise yes, it would be suitable to use IEndpointBehavior.
Thx
I'm trying to implement "some sort of" server-client & zero-config security for some WCF service.
The best (as well as easiest to me) solution that I found on www is the one described at http://www.dotnetjack.com/post/Automate-passing-valuable-information-in-WCF-headers.aspx (client-side) and http://www.dotnetjack.com/post/Processing-custom-WCF-header-values-at-server-side.aspx (corrisponding server-side).
Below is my implementation for RequestAuth (descibed in the first link above):
using System;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
namespace AuthLibrary
{
/// <summary>
/// Ref: http://www.dotnetjack.com/post/Automate-passing-valuable-information-in-WCF-headers.aspx
/// </summary>
public class RequestAuth : BehaviorExtensionElement, IClientMessageInspector, IEndpointBehavior
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string headerName = "AuthKey";
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string headerNamespace = "http://some.url";
public override Type BehaviorType
{
get { return typeof(RequestAuth); }
}
protected override object CreateBehavior()
{
return new RequestAuth();
}
#region IClientMessageInspector Members
// Keeping in mind that I am SENDING something to the server,
// I only need to implement the BeforeSendRequest method
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
throw new NotImplementedException();
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
MessageHeader<string> header = new MessageHeader<string>();
header.Actor = "Anyone";
header.Content = "TopSecretKey";
//Creating an untyped header to add to the WCF context
MessageHeader unTypedHeader = header.GetUntypedHeader(headerName, headerNamespace);
//Add the header to the current request
request.Headers.Add(unTypedHeader);
return null;
}
#endregion
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
throw new NotImplementedException();
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
throw new NotImplementedException();
}
public void Validate(ServiceEndpoint endpoint)
{
throw new NotImplementedException();
}
#endregion
}
}
So first I put this code in my client WinForms application, but then I had problems signing it, because I had to sign also all third-party references eventhough http://msdn.microsoft.com/en-us/library/h4fa028b(v=VS.80).aspx at section "What Should Not Be Strong-Named" states:
In general, you should avoid strong-naming application EXE assemblies. A strongly named application or component cannot reference a weak-named component, so strong-naming an EXE prevents the EXE from referencing weak-named DLLs that are deployed with the application.
For this reason, the Visual Studio project system does not strong-name application EXEs. Instead, it strong-names the Application manifest, which internally points to the weak-named application EXE.
I expected VS to avoid this problem, but I had no luck there, it complained about all the unsigned references, so I created a separate "WCF Service Library" project inside my solution containing only code above and signed that one.
At this point entire solution compiled just okay.
And here's my problem:
When I fired up "WCF Service Configuration Editor" I was able to add new behavior element extension (say "AuthExtension"), but then when I tried to add that extension to my end point behavior it gives me:
Exception has been thrown by the target of an invocation.
So I'm stuck here.
Any ideas?
You have some:
throw new NotImplementedException();
in your code. These could be the exceptions that are being thrown. Try removing these and see if you get the same error.
Shiraz Bhaiji is right. The framework does call those methods that you are throwing not implemented exceptions. Remove that.