Handle Json Request data in WCF REST Service POST method - c#

i am creating the REST service with POST method and OBJECT as input param. while client request am unable to get the actual JSON data client have posted. Is there any way to dig the JSON code from the C# WCF service.
My code:
namespace ACTService
{
public class AssortmentService : IAssortmentService
{
public void DeleteColor(DeleteColorContarct objdelcolor)
{
new Methods.ColorUI().DeleteColorDetails(objdelcolor);
}
}
}
and my interface as
namespace ACTService
{
[ServiceContract]
public interface IAssortmentService
{
[OperationContract]
[WebInvoke(UriTemplate = "DeleteColor", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json,BodyStyle=WebMessageBodyStyle.Wrapped)]
void DeleteColor(DeleteColorContarct objColor);
}
}
I need to access the JSON format in other class file ColorUI

WCF provides a lot of extensible points one of them is a feature called MessageInspector. You can create a custom message inspector to receive the request before it get de-serialized to C# object. And do what ever you can with Raw request data.
In order to implement it you would need to implement System.ServiceModel.Dispatcher.IDispatchMessageInspector interface like below:
public class IncomingMessageLogger : IDispatchMessageInspector
{
const string MessageLogFolder = #"c:\temp\";
static int messageLogFileIndex = 0;
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
string messageFileName = string.Format("{0}Log{1:000}_Incoming.txt", MessageLogFolder, Interlocked.Increment(ref messageLogFileIndex));
Uri requestUri = request.Headers.To;
HttpRequestMessageProperty httpReq = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
// Decode the message from request and do whatever you want to do.
string jsonMessage = this.MessageToString(ref request);
return requestUri;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
}
Here's the complete code snippet gist. Actual source.
Now you need to add this Message inspector to end point behavior. To achieve that you would be implementing System.ServiceModel.Description.IEndpointBehavior interface like below:
public class InsepctMessageBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new IncomingMessageLogger());
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
Now if you are on selfhosting i.e. you are hosting your service programmatically you can directly attach this newly implemented behavior to your service end point. E.g.
endpoint.Behaviors.Add(new IncomingMessageLogger());
But If you have hosted the WCF Rest service in IIS then you would be injecting the new Behavior via configuration. In order to achieve that you have to create an additional class derived from BehaviorExtensionElement:
public class InspectMessageBehaviorExtension : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(InsepctMessageBehavior); }
}
protected override object CreateBehavior()
{
return new InsepctMessageBehavior();
}
}
Now in your configuration first register the behavior under system.servicemodel tag:
<extensions>
<behaviorExtensions>
<add name="inspectMessageBehavior"
type="WcfRestAuthentication.MessageInspector.InspectMessageBehaviorExtension, WcfRestAuthentication"/>
</behaviorExtensions>
</extensions>
Now add this behavior to the Endpoint behavior:
<endpointBehaviors>
<behavior name="defaultWebHttpBehavior">
<inspectMessageBehavior/>
<webHttp defaultOutgoingResponseFormat="Json"/>
</behavior>
</endpointBehaviors>
set the attribute behaviorConfiguration="defaultWebHttpBehavior" in your endpoint.
That's it your service will now capture all the messages before deserializing them.

Related

How to programmatically add a SOAP header based on a generated proxy class

I'm trying to consume a SOAP webservices provided by a third party. I don't have any control of that webservice. I'm consuming the webservice using a Low Code platform called OutSystems. OutSystems unfortunately doesn't recognize a SOAP header that has to be send with the request so I'll have to add it myself by extending the platform functionality with some custom c# code.
The SOAP Extensibility API gives me access to the WCF ClientCredentials, ServiceEndpoint, IClientChannel and CommunicationState objects. It also provides a method to register an endpoint behavior, using a IEndpointBehavior object.
Using svcutil I've been able to generate proxy classes for the data of the message, including the SOAP header that I should add.
Ideally I'm looking for a way to instantiate an object of the proxy of the header and then somehow pass that to the service. But here is where i'm stuck. I/m not able to find a way to use that object as a SOAP header.
The documentation of OutSytems also provides an example about adding a soap header using .net code. They use MessageHeader.CreateHeader to create a new element with a given element name, namespace and value. So this is also a place where i'm stuck. It would be great if I could use the proxy class here, but this will only allow me to set it as the value. This way I end up with a duplicate 'root' element.
Using the code below:
class AddSoapHeaderMessageInspector : IClientMessageInspector {
object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel) {
// before sending a request, add a new SOAP header, specifying its name, namespace and value
request.Headers.Add(MessageHeader.CreateHeader("MySoapHeader", "http://my-namespace.com", mySOAPHeader));
return request;
}
void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState) {
// here you would handle the web service response
}
}
Would result in XML like
<MySoapHeader><MySoapHeader><element1><element2></MySoapHeader></MySoapHeader>
While it should look like
<MySoapHeader><element1><element2></MySoapHeader>
The solution we have now is one where we've implemented a class that extends MessageHeader. In the OnWriteHeaderContents of that class we manually write the content of the header in code. Unfortunately this is cause some namespace issues at the server side.
I'm posting this on stackoverflow instead of the OutSystems forum because I consider this more of a WCF/C# question than an OutSystems question.
You can add soap header in the implementation class by implementing IClientMessageInspector interface.
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageHeader header = MessageHeader.CreateHeader("MySoapHeader", "http://my-namespace.com", "asdas");
request.Headers.Add(header);
return null;
}
}
Add clientmessagelogger to clientruntime:
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
{
public Type TargetContract => throw new NotImplementedException();
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
Add Attribute to Interface of proxy class:
[CustContractBehavior]
public interface IService {
}
This is the soap message received by the server:
To learn more about IClientMessageInspector, please refer to the following link:
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.dispatcher.iclientmessageinspector?view=dotnet-plat-ext-3.1

Action property is null in message request in rest service C#

I have a REST service in C# as shown below :
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(UriTemplate="/GetData"]
[OperationContractAttribute(Action = "urn:crud:insert/IService1/GetData")]
string GetData(string value);
}
When I send my custom header details to ServerMessageInspector, then I am always getting action property as null
public class StringTrimmingMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request,
IClientChannel channel, InstanceContext instanceContext)
{
if(request.Header.Action!=null) // Issue : this property is always null
{
}
}
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
Would you please help or suggest me how can i set this property, same example works fine when i use WCF service but my requirement to use REST service only.

IEndpointBehavior life cycle / logging service calls

I'm trying to log all outbound requests that go to service references, including the full request and response body. I thought I had a solution using behaviorExtensions but, after deploying, it became clear that the extension was shared between multiple requests.
Here's my current code:
public class LoggingBehaviorExtender : BehaviorExtensionElement
{
public override Type BehaviorType => typeof(LoggingRequestExtender);
protected override object CreateBehavior() { return new LoggingRequestExtender(); }
}
public class LoggingRequestExtender : IClientMessageInspector, IEndpointBehavior
{
public string Request { get; private set; }
public string Response { get; private set; }
#region IClientMessageInspector
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
Request = request.ToString();
Response = null;
return null;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Response = reply.ToString();
}
#endregion
#region IEndpointBehavior
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
#endregion
}
Then, when I reach the point to log, I extract the behavior...
var lre = client.Endpoint.Behaviors.OfType<LoggingRequestExtender>().FirstOrDefault();
var req = lre?.Request;
var resp = lre?.Response;
Adding debugging logging to the LoggingRequestExtender, I found it was only instantiated once for multiple requests.
Is there a way to make sure this behavior class is instantiated fresh for each thread? Or is there a better way of getting the full request / response body when making service calls?
Edit / Partial answer:
Since writing this I have discovered that the value returned by BeforeSendRequest is passed into AfterReceiveReply as the correlationState so I can connect the request and response using a guid:
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
var guid = Guid.NewGuid();
WebServiceLog.LogCallStart(guid, channel.RemoteAddress.ToString(), request.ToString());
return guid;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Guid guid = (Guid)correlationState;
WebServiceLog.LogCallEnd(guid, reply.ToString());
}
I see two flaws to this approach. One, which is livable, is that this requires a log insert and then update rather than a single insert.
The second is more of an issue: In the case of an exception (e.g. timeout), we never hit AfterRecieveSupply so the log doesn't know what happened. I can separately log the exception...
try
{
response = client.SomeFunction(request);
}
catch (Exception ex)
{
AppLog.Error("Some function failed", ex);
}
... but I can't see a way of accessing the guid outside of BeforeSendRequest / AfterReceiveReply so I have nothing to tie the exception log to the service request log.
There are several approaches to this.
1, The situation you have described with having to log calls separately doesn't have to be like that. If your WCF service is in a non load balanced server just add the request to a MemoryCache using the Guid as a key. When the request comes in then pull off the request and log in one go. To capture the timed out calls you could run a process on a thread that would check the MemoryCache every x minutes to pull out and log (using an adequate lock to ensure thread saftey).
If the WCF service is in a load balanced environment then all you do is the same as above but store to a no sql type data store.
2, Is the code that makes the outbound calls within your scope for change? If so, you can forgo creating a behavior extension and create a bespoke message logger instead. Using a class that implements IDisposable you can write nice code like this..
RequestMessage request = new RequestMessage();
ResponseMessage response = null;
using (_messageLogger.LogMessage(request, () => response, CallContextHelper.GetContextId(), enabled))
{
response = _outboundService.DoSomething(request);
}
This will then not need another process to capture any timed out threads which will be handled in the dispose method.
If you need more clarity then let me know, hopefully this helps you...

Dependency Injection for WCF Custom Behaviors

In my WCF service I have a custom message inspector for validating incoming messages as raw XML against an XML Schema. The message inspector has a few dependencies that it takes (such as a logger and the XML schema collection). My question is, can I use a Dependency Injection framework (I'm using Ninject at the moment) to instantiate these custom behaviours and automatically inject the dependencies?
I've made a simple example demonstrating the concept:
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Ninject.Extensions.Logging;
public class LogMessageInspector : IDispatchMessageInspector
{
private readonly ILogger log;
public LogMessageInspector(ILogger log)
{
this.log = log;
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
LogMessage(ref request);
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
LogMessage(ref reply);
}
private void LogMessage(ref Message message)
{
//... copy the message and log using this.log ...
}
}
public class LogMessageBehavior : IEndpointBehavior
{
private readonly IDispatchMessageInspector inspector;
public LogMessageBehavior(IDispatchMessageInspector inspector)
{
this.inspector = inspector;
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this.inspector);
}
public void Validate(ServiceEndpoint endpoint) { }
}
How can I go about injecting an ILogger into LogMessageInspector and a LogMessageInspector into LogMessageBehavior?
Second question, is this overkill?
Edit: I can get this to work if I build my service in code because I create the behaviour using Ninject. However, when configuring the service via config, I need to add an additional class that extends BehaviorExtensionElement. This class is created by WCF and I can't seem to find a way to cause that to be created by Ninject instead. Configured in code:
static void Main(string[] args)
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IEchoService>().To<EchoService>();
kernel.Bind<LogMessageInspector>().ToSelf();
kernel.Bind<LogMessageBehavior>().ToSelf();
NinjectServiceHost<EchoService> host = kernel.Get<NinjectServiceHost<EchoService>>();
ServiceEndpoint endpoint = host.AddServiceEndpoint(
typeof(IEchoService),
new NetNamedPipeBinding(),
"net.pipe://localhost/EchoService"
);
endpoint.Behaviors.Add(kernel.Get<LogMessageBehavior>());
host.Open();
Console.WriteLine("Server started, press enter to exit");
Console.ReadLine();
}
}
This works fine, but I don't know how to create the behaviour when configured via my app.config:
<system.serviceModel>
<services>
<service name="Service.EchoService">
<endpoint address="net.pipe://localhost/EchoService"
binding="netNamedPipeBinding"
contract="Contracts.IEchoService"
behaviorConfiguration="LogBehaviour"
/>
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="logMessages" type="Service.LogMessagesExtensionElement, Service" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="LogBehaviour">
<logMessages />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
public class LogMessagesExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(LogMessageBehavior); }
}
protected override object CreateBehavior()
{
//how do I create an instance using the IoC container here?
}
}
How can I go about injecting an ILogger into LogMessageInspector and a
LogMessageInspector into LogMessageBehavior?
The approach has been described here
UPDATE
Please correct me if I'm wrong but I guess the question boils down to how could you get an instance of Ninject kernel in BehaviorExtensionElement.CreateBehavior? The answer depends on your hosting scenario. If hosted under IIS you could add something like this to your NinjectWebCommon:
public static StandardKernel Kernel
{
get { return (StandardKernel)bootstrapper.Kernel; }
}
Since you seem to be self-hosting, you might want to go for a static instance of the kernel too. In my view, however, this is not a terribly good idea.
I'd actually vote for your own approach and configure the behavior programmatically unless BehaviorExtensionElement is necessary because you need to be able to configure the behavior through the config file.
is this overkill?
It depends, but definitely not if you're going to unit test the implementation.
Instead of validation raw XML against an XML schema, why not take a more object oriented approach? You could for instance model each operation as a single message (a DTO) and hide the actual logic behind a generic interface. So instead of having a WCF service which contains a MoveCustomer(int customerId, Address address) method, there would be a MoveCustomerCommand { CustomerId, Address } class and the actual logic would be implemented by a class that implements the ICommandHandler<MoveCustomerCommand> interface with a single Handle(TCommand) method.
This design gives the following advantages:
Every operation in the system gets its own class (SRP)
Those message/command objects will get the WCF contract
The WCF service will contain just a single service class with a single method. This leads to a WCF service that is highly maintainable.
Allows adding cross-cutting concerns by implementing decorators for the ICommandHandler<T> interface (OCP)
Allows validation to be placed on the message/command objects (using attributes for instance) and allows this validation to be added again by using decorators.
When you apply a design based around a single generic ICommandHandler<TCommand> interface, its very easy to create generic decorators that can be applied to all implementations. Some decorators might only be needed to be applied when running inside a WCF service, others (like validation) might be needed for other application types as well.
A message could be defined as follows:
public class MoveCustomerCommand
{
[Range(1, Int32.MaxValue)]
public int CustomerId { get; set; }
[Required]
[ObjectValidator]
public Address NewAddress { get; set; }
}
This message defines an operation that will move the customer with CustomerId to the supplied NewAddress. The attributes define what state is valid. With this we can simply do object based validation using .NET DataAnnotations or Enterprise Library Validation Application Block. This is much nicer than having to write XSD based XML validations which are quite unmaintainable. And this is much nicer than having to do complex WCF configurations as you are currently trying to solve. And instead of baking this validation inside the WCF service, we can simply define a decorator class that ensures every command is validated as follows:
public class ValidationCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratedHandler;
public ValidationCommandHandlerDecorator(
ICommandHandler<TCommand> decoratedHandler)
{
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
// Throws a ValidationException if invalid.
Validator.Validate(command);
this.decoratedHandler.Handle(command);
}
}
This ValidationCommandHandlerDecorator<T> decorator can be used by any type of application; not only WCF. Since WCF will by default not handle any thrown ValidationException, you might define a special decorator for WCF:
public class WcfFaultsCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratedHandler;
public WcfFaultsCommandHandlerDecorator(
ICommandHandler<TCommand> decoratedHandler)
{
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
try
{
this.decoratedHandler.Handle(command);
}
catch (ValidationException ex)
{
// Allows WCF to communicate the validation
// exception back to the client.
throw new FaultException<ValidationResults>(
ex.ValidationResults);
}
}
}
Without using a DI container, a new command handler could be created as follows:
ICommandHandler<MoveCustomerCommand> handler =
new WcfFaultsCommandHandlerDecorator<MoveCustomerCommand>(
new ValidationCommandHandlerDecorator<MoveCustomerCommand>(
// the real thing
new MoveCustomerCommandHandler()
)
);
handler.Handle(command);
If you want to know more about this type of design, read the following articles:
Meanwhile... on the command side of my architecture
Writing Highly Maintainable WCF Services
Try having your LogMessageBehavior also use BehaviorExtensionElement as its base class, then you should be able to do the following:
public override Type BehaviorType
{
get { return this.GetType(); }
}
protected override object CreateBehavior()
{
return this;
}

Providing a factory instead of a Type in WCF ServiceHost

Is there any way to extend ServiceHost so that it accepts a factory?
I would like to use dynamic service proxies for some preprocessing of WCF calls without touching the service implementation.
EDIT
Now the ServiceHost creation looks like
var host = new ServiceHost(typeof(MyService));
and i would like to use something like
var factory = new ServiceProxyFactory<MyService>();
var host = new MyServiceHost(typeof(MyService), factory);
The interface i was looking for is IInstanceProvider.
public class MyServiceInstanceProvider<TService> : IInstanceProvider where TService : new()
{
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return ServiceFactory.Create<TService>();
}
public object GetInstance(InstanceContext instanceContext)
{
return ServiceFactory.Create<TService>();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
return;
}
}
public class MyEndpointBehavior<TService> : IEndpointBehavior where TService : new()
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new MyServiceInstanceProvider<TService>();
}
public void Validate(ServiceEndpoint endpoint)
{
return;
}
}
public class MyServiceHost<TService> : ServiceHost where TService : new()
{
public MyServiceHost(params Uri[] baseAddresses)
:base(typeof(TService), baseAddresses)
{
}
public override System.Collections.ObjectModel.ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints()
{
var endpoints = base.AddDefaultEndpoints();
foreach (var endpoint in endpoints)
{
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
return endpoints;
}
public override void AddServiceEndpoint(ServiceEndpoint endpoint)
{
base.AddServiceEndpoint(endpoint);
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
}
What you describe is not really possible with .NET...
You can implement a custom ServiceHost which allows you to customize the behaviour of the ServiceHost and/or the IDispatchMessageInspector which allows you inspect/modify any message inbound and outbound... IF you really wnat to implement some sort of "dynamic routing" then there is always the Routing capability of WCF...
Other options (though no 100% solution):
WCF service returning another service (service factory?)
WCF and factory design pattern
http://msdn.microsoft.com/en-us/library/aa702697.aspx
EDIT - I stand corrected:
It is not really possible to use a usual Factory BUT WCF provides the possibility to plug in an IInstanceProvider either at the Service or the Endpoint level...
For further reference see the following links
http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx
http://msdn.microsoft.com/library/system.servicemodel.dispatcher.iinstanceprovider.aspx
How do I pass values to the constructor on my wcf service?
http://geekswithblogs.net/13DaysaWeek/archive/2010/12/01/dependency-injection-and-wcf-services.aspx
http://www.eggheadcafe.com/tutorials/aspnet/b428fb65-08b4-45c8-97cd-47ee1a1eaf41/composing-wcf-applications.aspx

Categories