Resolve a URI to an EndpointAddress - wcf

I currently have a WCF client that is able to do ad-hoc service discovery to find (unknown) services running on the local subnet. I would like to implement a way for the user to specify a service endpoint to use by entering a URI into a text box, and for the client to resolve this URI to an EndpointAddress, and in the process gather additional metadata about the service. Namely, I need to gather the EndpointIdentity and additional data exposed in the Extensions property of the EndpointDiscoveryBehavior.
I am trying to achieve this by using DiscoveryClient.Resolve(), but I am only receiving null for the ResolveResponse.EndpointDiscoveryMetadata property.
String Address = "net.tcp://machine-name:12345/MyService"
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var criteria = new ResolveCriteria()
{
Address = new EndpointAddress(Address)
};
var result = discoveryClient.Resolve(criteria);
//scv is null here.....
var svc = result.EndpointDiscoveryMetadata;
I've found a lot of information out there regarding DiscoveryClient.Find(), but not so much about DiscoveryClient.Resolve().
So my questions are:
Is this the intended use of DiscoveryClient.Resolve()?
Is MetadataResolver more appropriate here?
How does one resolve an URI to a EndpointAddress and obtain other metadata?

I think you are trying to replicate functionality of svcutil.exe. In that case you may have to resolve the mex endpoint first and query service metadata from that endpoint (IMetaDataExchange). The SPN identity should be in the metadata.
Also see reference http://msdn.microsoft.com/en-us/library/ms733130.aspx

I achieved what I wanted to do like so:
String Address = "net.tcp://machine-name:12345/MyService"
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
var endpoint = new EndpointAddress(new Uri(Address));
var criteria = new ResolveCriteria()
{
Address = endpoint
};
var result = discoveryClient.Resolve(criteria);
var mexClient = new MetadataExchangeClient(MetadataExchangeBindings.CreateMexTcpBinding());
var contracts = new List<ContractDescription>() { ContractDescription.GetContract(typeof(RuntimeService.Services.IWorkflowService)) };
var metaResult = MetadataResolver.Resolve(contracts, endpoint, mexClient);
var svc = metaResult.First();
I am able to get to the extension data through result and svc provides me with the correct EndpointAddress complete with the correct identity.
Thanks to #YK1 for pushing me in the right direction.

Related

IBM Worklight 6 - How would i get client IP address on adapter side

I want to have client ip address on adapter side but i don't know what is the worklight api for that. I search for it but no luck.
I used this api on client side code which is given below
WL.Device.getNetworkInfo(function (networkInfo) {
console.log ("Ip address of device "+networkInfo.ipAddress);
});
It works fine and i can pass this to the adapter from client side. But i just wanted to know whether the same thing can be implemented on server side in adapter procedure.
And I also used this code which is given below
var request = WL.Server.getClientRequest();
var userAgent = request.getHeader("User-Agent");
Can we get Ip address here using this API in adapter procedure.
WL.Server.getClientRequest() will return a reference to HttpServletRequest Java object (http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html). You can use Java APIs to get the info you need, e.g.
var request = WL.Server.getClientRequest();
request.getRemoteAddr()
request.getRemoteHost()
Note that in case there are gateways/proxies between client and your WL server (and there most probably are) above APIs will get you info about proxies. In case you need the actual device IP you can use
var request = WL.Server.getClientRequest();
var IPAddress = request.getHeader('x-forwarded-for');
UPDATE:
In order to iterate over headers enumeration and get the full list of request headers use following code:
var headers = {};
var request = WL.Server.getClientRequest();
var headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
var headerName = headerNames.nextElement();
var headerValue = request.getHeader(headerName);
headers[headerName] = headerValue;
}

Using WS2007FederationHttpBinding with SOAP 1.1

Is there a way to use WS2007FederationHttpBinding binding, but generate SOAP 1.1 request envelop? I need to use WS2007FederationHttpBinding to authenticate using a bearer token acquired from an STS service. Here is my bindings:
private static Binding GetWS2007FederationHttpBinding()
{
var binding = new WS2007FederationHttpBinding(
WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
//binding.MessageVersion.Addressing = AddressingVersion.WSAddressingAugust2004;
//binding.MessageVersion.Envelope = EnvelopeVersion.Soap11;
// or
//binding.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;
return binding;
}
But I can't change binding.MessageVersion because it's a read-only property?
You would need a custom binding for that. One way would be to statically declare a custom binding equivalent to WS2007FederationHttpBinding - could take a while to fine tune it. Or you could create WS2007FederationHttpBinding in code (like you do), clone it into a custom binding:
CustomBinding outputBinding = new CustomBinding(federationBinding.CreateBindingElements());
and then find the text message encoding channel and change its soap version.

implementing routing into my wcf service

I have clients that upload files to my server using a wcf service with streaming. The code on the client is something like this (omitting some details):
NetTcpBinding binding = new NetTcpBinding();
EndpointAddress address = new EndpointAddress("net.tcp://" + ipAddress + ":5000/DataUploader");
ChannelFactory<IDataUploader> channel = new ChannelFactory<IDataUploader>(binding, address);
IDataUploader uploader = channel.CreateChannel();
try
{
uploader.Upload(msg);
ConsoleText.Record("The file was sent...\n");
}
catch (CommunicationException)
{
ConsoleText.Record("The file was not sent...\n" + "Interrupted connection...\n");
}
finally
{
uploadStream.Close();
((IClientChannel)uploader).Close();
}
I want to implement a routing service between server and client, the routing service would be something like this:
private static void ConfigureRouterViaCode(ServiceHost serviceHost)
{
string clientAddress = "http://localhost:5000/DataUploader";
string routerAddress = "http://localhost:5000/RouterService";
Binding routerBinding = new WSHttpBinding();
Binding clientBinding = new WSHttpBinding();
serviceHost.AddServiceEndpoint(typeof(IRequestReplyRouter), routerBinding, routerAddress);
ContractDescription contract = ContractDescription.GetContract(typeof(IRequestReplyRouter));
ServiceEndpoint client = new ServiceEndpoint(contract, clientBinding, new EndpointAddress(clientAddress));
RoutingConfiguration rc = new RoutingConfiguration();
List<ServiceEndpoint> endpointList = new List<ServiceEndpoint>();
endpointList.Add(client);
rc.FilterTable.Add(new MatchAllMessageFilter(), endpointList);
serviceHost.Description.Behaviors.Add(new RoutingBehavior(rc));
}
It's confused how I can connect my client to the routing service first. Is this a good approach?? Thanks.
your approach is correct. On the client, change the address pointing to the routing service, leaving all other settings as they were. I suggest you study http://msdn.microsoft.com/en-us/library/ee517423.aspx or find some demo routing implementations.

WCF service discovery with metadata

Hi I'm looking for a WCF example which include service discovery and a way to discover/detect the binding type, I think it could be done using metadata exchange
.
I just found the correct answer, here are the steps to complete the task:
Add a mex endpoint.
Add metadata exachange behaviour.
in the client application use discovery with metadata criteria.
Discovery with metdatada criteria
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
FindCriteria findCriteria = FindCriteria.CreateMetadataExchangeEndpointCriteria (ContractType);
findCriteria.Duration = TimeSpan.FromSeconds(15);
findCriteria.MaxResults = 1;// MaxResults;
FindResponse result = discoveryClient.Find(findCriteria);
discoveryClient.Close();
ServiceEndpointCollection eps = MetadataResolver.Resolve(ContractType, result.Endpoints[0].Address);
return eps[0].Binding;

WCF: Why does passing in a remote endpoint fail?

The problem I am having connecting a wcf client application to a host running on a separate machine is documented in a question previously asked:
WCF: Why does passing in a remote endpoint fail?
However, the solution provided here says you need to use a SpnEndpointIdentity with an empty string. Since my code doesn't look anything like the case in the example I have referenced, I need to know what to do with the SpnEndpointIdentity object I have created.
I have a ChannelFactory upon which I call Create channel, passing in an EndpointAddress:
public override void InitialiseChannel()
{
SpnEndpointIdentity spnEndpointIdentity = new SpnEndpointIdentity("");
var address = new EndpointAddress(EndpointName);
Proxy = ChannelFactory.CreateChannel(address);
}
(NB: ChannelFactory is of type IChannelFactory, where T is the service contract interface)
So what do I do with spnEndpointIdentity? I can't pass it to CreateChannel.
Or perhaps I can use it somehow when I create the channel factory:
private ChannelFactory<T> CreateChannelFactory()
{
var binding = new NetTcpBinding
{
ReaderQuotas = { MaxArrayLength = 2147483647 },
MaxReceivedMessageSize = 2147483647
};
SpnEndpointIdentity spnEndpointIdentity = new SpnEndpointIdentity("");
var channelFactory = new ChannelFactory<T>(binding);
return channelFactory;
}
Again, I can't pass it into the constructor, so what do I do with it?
Thanks.
You almiost got it.
What you're missing is that you associate the EndpointIdentity with the EndpointAddress, and then provide that to CreateChannel():
SpnEndpointIdentity spnEndpointIdentity = new SpnEndpointIdentity("");
var address = new EndpointAddress(EndpointName, spnEndpointIdentity);