I currently have a WCF service that is able to obtain the client IP address using the following code;
private static string GetClientIPAddress()
{
RemoteEndpointMessageProperty clientEndpoint =
OperationContext.Current.IncomingMessageProperties[
RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
return clientEndpoint.Address;
}
However, when we put a WCF routing service in front of the existing service, we now find that that the reported IP address is that of the server hosting the routing service.
Is it possible for the client IP address to be retained all the way though?
Related
As I know, in Azure service fabric, service communication can be possibles either by directly accessing the endpoints (or) reverse-proxy.
Currently I'm directly accessing the other service endpoints using below code:
var service = $"fabric://myapp/**service1**";
var servicePartitionResolver = ServicePartitionResolver.GetDefault();
var partition = await servicePartitionResolver.ResolveAsync(new System.Uri(service),
new ServicePartitionKey(), default(CancellationToken));
var serviceEndpointJson = partition.GetEndpoint().Address;
string endpointUrl = JObject.Parse(serviceEndpointJson)["Endpoints"][string.Empty].Value<string>();
Will this approach work if service1 instance is not available on expected node1 but available on node2 of the SF cluster?
Is directly accessing service endpoints - approach uses 'Naming Service' like reverse-proxy approach to identify the requested service address via service url?
Any disadvantages of using above direct access call implementation to discover services for internal service communication?
The resolved endpoint should work, but you can do this in a simpler way:
Use the built-in DNS to communicate between services using HTTP.
Use SF Remoting to communicate between services.
The DNS allows you to get an endpoint by passing in the application and target service details.
SF remoting works in a similar way. The main advantage of the last, is that the SF remoting client has built-in transient error handling (it retries calls whenever the remote service is temporarily unavailable).
Hello BizTalk and WCF experts
I need your help todo a implementation for this scenario:
I have created a BizTalk application without schemas, orchestrations but just with a send port pipeline that look at the soap action on the request message and send the request to the correct destination service.
I have also created a in-process WCF-Custom receive port that my send port subscribe and I have defined following in-process custom URL "http://localhost:8080/bts/services/serviceRoute.svc".
Instead of calling the above metioned URL i want an IIS service endpoint that receive all the request and send it to ny custom url.
So i want a IIS svc endpoint without specific schema but a service endpoint that can receive any request no matter operationsname and send the request to my BizTalk receive port (my WCF-Custom receive port).
Can anyone tell me how I can define/create a IIS service endpoint for this scenario or any other way I can solve this issue.?
Thanks for your help..
Very important point: BizTalk already does this. You don't need the extra IIS service.
BizTalk Receive Locations are not Schema bound. They will happily accept any message type. The only validation happens if you implement it.
So, I would start with a plain WCF-WebHttp endpoint hosted In-Process or IIS or WCF-BasicHttp/basicHttpBinding to have the Action automatically Promoted (IIRC, been a while ;).
You can configure the URL, security and what not any way you need in IIS.
Create a service with a method that receives a System.ServiceModel.Channels.Message class, like this interface:
[ServiceContract(Namespace = "http://yournamespace")]
public interface IRouter
{
[OperationContract(Action = "*", ReplyAction = "*", Name = "*")]
[WebGet]
Message RouteMessage(Message incomingRequest);
}
This will receive any message, including non-soap messages, so you can create your routing logic.
Message class has some useful members, like Headers property and CreateMessage method, that you can use to create a copy of original message and redirect to its destination, or simply extract the data for logging.
EDIT: adding some information (some doubts in comments)
Using the code above, you can simply redirect the incomming message to another endpoint, like this:
/* "endpointConfigurationName" is the name of a client endpoint, that is in Web.config, like this for instance:
<endpoint name="endpointConfigurationName" binding="basicHttpBinding" bindingConfiguration="someBindingConfiguration" behaviorConfiguration="someBehaviorConfiguration" contract="IRouter" />
notice that there is not an address defined, you can define in code */
using (var factory = new ChannelFactory<IRouter>("endpointConfigurationName", new EndpointAddress("http://destinationEndpoint")))
{
// create a channel to send the resquest
IRouter router = factory.CreateChannel();
// get the response
var reply = router.ProcessarMensagem(incomingRequest);
}
This is a very simple example, but contains the base logic.
I have one SOAP service which is consuming 2nd WCF service. WCF service is designed to use NET.MSMQ binding.
Both SOAP service and WCF service are hosted on same server(172.16.26.59)
In the web.config of SOAP service I when I use hard coded IP or localhost then it is able to call NET.MSMQ WCF service successfuly.
Here I am using public Queue.
But if I use FQDN(MTRWebservices.NNYM.NNT) instead of IP or localhost then it doesn't work.
Can anyone please help , why my SOAP service is not able to resolve FQDN (MTRWebservices.NNYM.NNT) to its corresponding IP address.
It has entry in host file , I verified this by pinging MTRWebservices.NNYM.NNT , it return me correct IP (172.16.26.59).
In real time this FQDN will act as a load balancer based CPU utilization.
Maybe I am mixing things, if this is the case, please let me know.
I want to provide a set of services through WCF regarding messages (this is an example). In this set I am going to have a "sendMessage" service and a "receiveMessage" service.
For the sendMessage, I want to use MSMQ, so the user can send the message to 100.000 other users and this will be processed in background.
For the receiveMessage I do not want to use MSMQ because I want the user to be served when he makes the request and get the response (MSMQ, in this case, is oneway).
I am using this code to start my host in an example application
static void Main(string[] args)
{
using (ServiceHost host =
new ServiceHost(typeof(Service), new Uri[] {
new Uri("net.msmq://localhost/private/loadqueue"),
new Uri("http://localhost:8383/") }))
{
host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
NetMsmqBinding binding = new NetMsmqBinding();
binding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;
binding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;
binding.ExactlyOnce = false;
host.AddServiceEndpoint(
typeof(IContract),
binding,
string.Empty);
host.AddServiceEndpoint(
typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex");
host.Open();
Console.WriteLine("service running");
Console.ReadLine();
}
}
The Contract looks like this
[ServiceContract(SessionMode=SessionMode.Allowed)]
[DeliveryRequirements(QueuedDeliveryRequirements = QueuedDeliveryRequirementsMode.Allowed)]
public interface IContract
{
[OperationContract(IsOneWay = true)]
void SendData(string msg);
}
When the client invokes the SendData service, the message is sent to the queue and after that it is consumed by the service.
I would like to create a second service which receives directly the message from the client (no queue in the middle).
The client would have only one web reference and if he calls service.SendData() the message is sent to the queue and if the client calls service.NetMethod() the service receives the message directly. This way it would be transparent for the client side developer if the service is using a queue or not and I would be able to group the services regarding their functions and not mechanisms. Would that be possible to make?
Thanks,
Oscar
WCF allows you to expose the same service contract across mixed transport bindings. For example, your service class has two operations, one one-way, and one request-response. You can expose this service across net.tcp:// and http:// on two endpoints (with different URIs).
However, what you want to do is have the different operations on your service contract exposed over different transports, and as far as I know WCF does not allow this.
The problem you have is that, as you say, the bi-directional operation cannot be supported under the msmq binding. So you would not be able to expose your entire contract across http and msmq simultaneously.
Is there any reason you cannot define two service contracts and host them in the same servicehost, as described here?
I have the following operation for hosting my client access policy in my WCF service:
[OperationContract]
[WebGet(UriTemplate = "/clientaccesspolicy.xml")]
XElement RetrieveClientAccessPolicy();
public XElement RetrieveClientAccessPolicy()
{
String policy = #"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
...
</access-policy>";
return XElement.Parse(policy);
}
When I try to connect to my the service from my silverlight app, I get an error because it can't find the client access policy. It's looking for it here:
http://MyServer/clientaccesspolicy.xml
When I browse there in IE, I get a 404. However, I can find the clientaccesspolicy.xml file if I browse to here:
http://MyServer/server/clientaccesspolicy.xml
How can I get my operation to make the client access policy file accessible from the root, and not from that directory (server is the service's name)?
I am guessing that you are not using IIS to host the service since you are trying to return the clientaccesspolicy.xml via a WCF call.
In the case of a self-hosted WCF service, I think you are going to have to set up a separate service endpoint and contract for your RetrieveClientAccessPolicy() call in your App.config. That service would have a baseAddress of http://localhost where your main service would have a base address of http://localhost/server.