Entity Framework data service request headers for mvc - c#

We have an Entity framework web service, that needs authentication to access. This authentication needs to happen every time a request is sent.
The system im editing has it working perfectly for a WPF application by overriding the OnSendingRequest event of the entity container from the mainWindow.xaml.cs file. then adding the authorization to the header. And i found a resource that tells me to do something similar, but i dont know how this works in a ASP.NET MVC project, since the resource seems to only give an example of how to do it for a single request, in WPF. How to: Set Headers in the Client Request (WCF Data Services
I need to make this same authentication header for the connection of the mvc project, for every request.

You can try message interceptor to insert authentication headers.
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
MessageHeader header1 = MessageHeader.CreateHeader("Testreply", "http://Test", "Test");
request.Headers.Add(header1);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
MessageHeader header = MessageHeader.CreateHeader("UserAgent", "http://User", "User1");
reply.Headers.Add(header);
return null;
}
}
[AttributeUsage(AttributeTargets.Interface)]
public class CustomBehavior : Attribute, IContractBehavior
{
public Type TargetContract => typeof(ServiceReference1.ICalculator);
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)
{
return;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
In the BeforeSendRequest method, you can insert a header, to apply this message interceptor, you need to add [CustomBehavior] in the client's service reference.
Like this:

Incase someone else finds this useful, i solved the problem by accident.
I made a static class, and a static method, that can be called from any page in the project. with this code:
var serviceUri = new Uri(WebConfigurationManager.AppSettings["DataServiceUri"]);
myService result = new myService(serviceUri);
result.SendingRequest += new EventHandler<SendingRequestEventArgs>((s, e) =>
{
string authenticationString = applicationName + " " + applicationId;
e.RequestHeaders.Add("Authorization", authenticationString);
});
return result;
This both creates and returns the instance of the service, to use in the calling method, and also automatically creates the Authorization and executes it.
This hasto be done on each of the controllers that communicates with the service.
Enjoy.

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

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...

Handle Json Request data in WCF REST Service POST method

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.

Is Hearbeat a good option for check client is alive in a not long running wcf service?

I have a wcf service (PerSession) that wrap libvlc for start and stop video streaming from ip camera. A client select the channel it want to receive streaming (unicast, multicast) and in the service side i start the streaming with libvlc (nVLC), this is not a long running task, it start the transmission and return the mrl quickly. Now i need a time based check if client is alive, for stop the transmission if client is not alive to save resources (cpu in the transcoding process, and bandwith in the streaming transmission). In my research i found the "hearbeat" concept but it is bounded to long running process in every explanation. My quests are:
Is hearbeat the solution to my problem or a time based mandatory ping from client to service is better in my situation.
Is mandatory a dual channel connection in my situation or with one-way i solve.
What binding are you using ?If you are not using webHttpBinding you could just registry for Closed event of IClientChannel and wcf handled everything for you. Your service contract will be like below.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple, AddressFilterMode = AddressFilterMode.Any)]
public partial class MyServiceContract :IMyServiceContract,IChannelInitializer, IContractBehavior
{
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
{
dispatchRuntime.ChannelDispatcher.ChannelInitializers.Add(this);
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
public void Initialize(System.ServiceModel.IClientChannel channel)
{
channel.Closed += new EventHandler(client_Disconnected);
}
private void client_Disconnected(object sender, EventArgs e)
{
IClientChannel channel =(IClientChannel)sender;
// free your resources here
}
}

How to pass dependencies to a WCF restful service

I am new to Rest services. I did fair bit of research on this topic but still not clearly understood. Hope someone clear this to me. Thanks in advance.
My client is going to execute a method on my service class through an url. All I understood is client going to call
localhost/service/get/customers
In my rest service I have dependencies like a IRepository so that I can go to database and fetch the records. If I go with constructor injection when would client call this constructor?
It looks like I need to use a service locator to fetch IRepository inside the method which I need it.
Doesn't this violate OOP principle? Is testing easy without DI?
Can anyone please clarify this.
For any service how do we expect client to know what is IRepository is what methods it does have?
Is isn't it for internal implementation purpose Do we need t expose to the client? Why should he bother about it? Can't I provide just Uri Which method to call (localhost/service/Products) and job done.
I will appreciate if you provide any live example.
Thanks a lot.
No, it will not violate OOP priciple, if you will resolve for dependency inside a method. But there is no need for that, you can use constructor Dependency Injection within WCF using Instance Provider and ServiceHostFactory, there is also good example in this question.
If you are self-hosting the service, it will be even more simpler because it requires implementing only IInstanceProvider and ServiceHost. Assuming that you have Service service with constructor taking an IDependency parameter:
public class CustomInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IDependency dependency;
public CustomInstanceProvider(IDependency dependency)
{
this.dependency = dependency;
}
public object GetInstance(InstanceContext instanceContext)
{
// Here you are injecting dependency by constructor
return new Service(dependency);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
}
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost(IDependency dependency, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new CustomInstanceProvider(dependency));
}
}
}
Then when creating service, use CustomServiceHost:
var serviceHost = new CustomServiceHost(dependency, typeof(Service), uris);

Categories