Regarding WCF service url & Mex Endpoint usage - c#

i am learning wcf so often questions comes to my mind.recently i developed a small calculator wcf service. i had three project one has service contract and another has wcf service with main class from where i self host the service. in app.config file i gave my endpoint address
net.tcp://localhost:5555/Calculator
i always thought that i have to give my service class name at the end of service url. in my apps my service url looks like above and Calculator is my service class name.
just few days ago i was browsing a wcf code and i saw that there service class name was chatsrv but service url would look like net.tcp://localhost:5555/chat
i like to know that can i give any name to my service at the end?
1) if so then how self host code can understand at which url service need to start ?
2) if i set false for <serviceMetadata httpGetEnabled="false"/> then how other client consuming my service because i have set httpGetEnabled="false" and self host the service but from other .net project i could consume that service by channel factory and as add reference? so tell me what people need to set httpGetEnabled="true" if false works fine?
whatever i know that if httpGetEnabled="false" then mex endpoint will not expose to other client and hence forth no other client may not be able to add reference to their project of my service reference. i am new so not good about the service internal. if possible please discuss it in detail.
3) why mex endpoint is required when client can instantiate & call service function through channel factory without mex endpoint then why & when mex endpoint would require?
thanks
UPDATE
1)
i like to know that can i give any url as endpoint address ?
i have given this net.tcp://localhost:5555/chat as my endpoint address and it works but if i give the endpoint address like net.tcp://localhost:5555/Mychat then does it work?
i like to know what is the convention of giving endpoint address url?
2) now regarding mex endpoint. in my service config file i disable mex like but still i saw any client can add reference like net.tcp://localhost:5555/chat/mex how it is possible ?
when mex is disable then mex point should not be expose or accessible before client...am i right?
please guide me. thanks

I'll try to answer some of your questions:
1) When you configure your service, you have to configure the endpoint URL, either with the popular config file or in code like this:
Dim URL as string = "http://ServerName:port/SomeClass/SomeFunction"
Dim ServiceHost As New ServiceHost(GetType(YourImplementationClass), URL)
Dim ServiceHostEndPoint As EndpointAddress = New EndpointAddressURL(URL)
ServiceHost.AddServiceEndpoint(GetType(iYourImplementationClass), binding, ServiceHostEndPoint.ToString)
ServiceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpsBinding(), "mex")
ServiceHost.Open()
2) You can give your clients the URL and xsl directly, but exposing your endpoint with Mex is easier for everyone. Also, if you make changes, they can re-reference your mex metadata and automatically update their interfaces.
3) mex isn't required if clients are configuring the endpoints themselves using the channel factory, it's just easier using mex. Just typing your endpoint URL into a browser will generate most of what they need to connect to your web service.
Hope that helps.

Comment out below line because it'll be added automatically while configuring the proxy in your configuration file where you defined endpoints of the service.
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
If you want to check, Right click on service proxy where you added service proxy, and select "Configure Service Reference" and you'll notice /mex is added in URL of the service at last

Related

How can I discover what kind of endpoints a service offers with ServicePartitionResolver?

I am trying to write a service resolver and for that I am currently using, as mentioned in https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication, the ServicePartitionResolver.
This all works fairly well so far. Given my service information, I am able to resolve a service like this:
var resolvedService = await ServicePartitionResolver.GetDefault().ResolveAsync(service.ServiceName, key, CancellationToken.None);
Now, in order to allow my services to communicate with each other, I am reading the endpoint address like this for the first one e.g.:
resolvedService.Endpoints.First().Address
This properly returns the required endpoint I returned in the OpenAsync method of my ICommunicationListener implementation.
Basically, this is all doing a fine job as long as the protocol is http.
As soon as I switch the protocol to something like for example tcp in my ServiceManifest.xml of the service where the request should go to:
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Protocol="tcp" Name="ServiceEndpoint" Type="Input" Port="3245" />
</Endpoints>
The ServiceResolver still resolves my endpoint to an address starting with http.
So, now my question - Am I simply doing something wrong? Because to me it seems like I can't really know what endpoint I am dealing with exactly. Even if this is not directly reflected in the Address, I could still just trim the http part from the endpoint string, but there is no information what kind of endpoint it is as well. So, technically, I can replace the http:// with blank, but it would be preferable to do this based on something I get back from Service Fabric instead of "because I know about the endpoint".
Any ideas?
The protocol definition from the manifest is not used define the endpoint. The communication listener implementation returns the endpoint from OpenAsync. So I'd recommend starting the search in there.
More info here and here.

How to route all traffic through https?

Service Fabric allows you to specify what endpoints it will listen on, and each service can expose different protocols like so:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(serviceContext => new OwinCommunicationListener(Startup.ConfigureApp,
serviceContext, ServiceEventSource.Current, "ServiceEndpointHttps")),
//you can add another one here like so:
new ServiceInstanceListener(serviceContext => new OwinCommunicationListener(Startup.ConfigureApp,
serviceContext, ServiceEventSource.Current, "ServiceEndpointUnSecured"))
};
}
In the ServiceManifest.xml file, we can specify these two endpoints:
<Endpoints>
<Endpoint Protocol="http" Name="ServiceEndpointUnsecured" Type="Input" />
<Endpoint Protocol="https" Name="ServiceEndpointHttps" Type="Input" />
</Endpoints>
We have 100 microservices, and we want to have only 1, central location where we configure whether the services are running through http or https.
Is it possible to change this setup so that we would have only 1 location that would be responsible for routing http or https for ALL services?
Depending on whether you are talking about communication between services within the cluster or from outside the cluster there are a few different approaches.
For service to service communication inside the cluster, it's all up to the client (e.g. the other service making the call). The reverse proxy, as Rogala mentions, would be the central solution. You can call the reverse proxy and it will use the Service Fabric naming service to route to the exposed endpoint. If you only expose https, it will be https, you can also configure the reverse proxy to always use https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reverseproxy-configure-secure-communication
For ingress to the cluster, a similar concept, having everything going through a gateway service inside the cluster, is the common pattern. The gateway service would then use the reverse proxy and thus the pattern described above: https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-connect-and-communicate-with-services#connections-from-external-clients
Yes, you could use a proxy like Apigee or Azure API management and have all traffic proxy through that central location. This provides major advantages around security and managing traffic.

Specify a single address for a self-hosted WCF service

I have a self-hosted WCF service written that needs to run on one specific address on a machine with multiple addresses. To that end, I have written the config so that the address to use is specified in the endpoint:
<endpoint address="http://A.B.C.D:8000/MyService" binding="webHttpBinding" name="MyServiceEndpoint" behaviorConfiguration="MyServiceBehavior" contract="IMyServiceInterface" />
When I run this app and start the service, it is running on ALL addresses rather than the one specified. I tried moving the address into the baseAddress field and leave the endpoint address blank, but got the exact same result. What am I missing?
OK, for anyone else who happens to run into this problem, it isn't with the service configuration, it's with the binding configuration.
The webHttpBinding binding has a hostNameComparisonMode property that defaults to StrongWildcard.
This means that an http service ignores the host name and responds to any hostname. As a side effect, it runs on all open addresses on the machine.
If this value is changed to Exact, then it uses the host name or IP address specified either in the endpoint or the base address.

Passing parameter to WCF Service Ctor from Proxy Client

This may be a basic question since I am new to WCF. I don't even know if this is supported or not.
I have a WCF Service called MyCustomService. I added this service reference in my client solution and now I can create a proxy object by calling:
MyCustomServiceClient myClient = new MyCustomServiceClient();
myClient.GetData();
myClient.GetData();
How, do I layout my Service so that I can pass the parameter during proxy instance creation i.e.
MyCustomServiceClient myClient = new MyCustomServiceClient("SomeString");
I noticed every method call I make creates a new instance of the MyCustomService(i.e I can get the breakpoint hit on MyCustomService Ctor). So, I want the value that I had passed when creating proxy object (i.e. SomeString) to exist for all the calls I make until the lifetime of myClient
Any ideas ?
The proxy generation feature of Visual Studio (or svcutil.exe) creates a proxy class with five different constructor signatures. The one that you are asking about, the constructor that takes a single string, is a very useful one, because it allows you to reference different client configurations from your app.config or Web.config file.
Take this extremely simple hypothetical configuration file:
<configuration>
<system.serviceModel>
<client>
<endpoint name="serverABinding" />
<endpoint name="serverBBinding" />
</client>
</system.serviceModel>
</configuration>
You can then control which binding you use for the proxy:
string endpointName = useB ? "serverBBinding" : "serverABinding";
var myClient = new MyCustomServiceClient(endpointName);
Of course, the endpoint bindings I've shown above are too simple to actually be useful, but hopefully you get the idea.
Your motivation isn't exactly clear, but it sounds like you want to control the proxy behavior across all proxy instances of your application. If that's what you want, then don't use a constructor: use the endpoint configuration in your app.config or Web.config file to control the proxy connection. The default endpoint configuration that is generated by Visual Studio uses an endpoint name that matches the default name of the proxy client. Change this endpoint definition, and you'll change the behavior of your service client.
Since you are new to WCF, my advice to you is this: learn all about configuration files. Once you understand a WCF configuration file, you understand WCF.
You can not have constructor with parameter in your WCF service, even when you try to create such service you will get below error.
The service type provided could not be loaded as a service because it
does not have a default (parameter-less) constructor. To fix the
problem, add a default constructor to the type, or pass an instance of
the type to the host.
Now if you want the data to persist for a client you can set ServiceInstanceContextMode as below as a attribute on Service Class
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service : IService

Is it better to specify a relative address in an endpoint or in a UriTemplate?

Is it better practice to specify a relative address in an endpoint for example
<endpoint address="json" ... />
or in the UriTemplates:
[WebGet(UriTemplate="json/....")]
What is better practice here? Does it matter? I know if I decide to change json to js later, I would have to change it in all the UriTemplates, but only one time in the endpoint, but what if I have multiple endpoints. I can't use the same address.
It is different things. Lets look to each of it.
'EndpointAddress provides a unique network address that a client uses to communicate with a service endpoint'. The endpoint address belongs to the service endpoint, which also contains the binding, contract and behaviors for the endpoint.
The endpoint address for a service can be specified either imperatively using code or declaratively through configuration. Defining endpoints in code is usually not practical because the bindings and addresses for a deployed service are typically different from those used while the service is being developed. It is more practical to define service endpoints using configuration.
In cases when do you need multiple endpoints defined in your configuration - you can manually instantiate Client using endpoint Name attribute instead of endpoint address.
'WebGetAttribute indicates that a service operation is logically a retrieval operation and that it can be called by the REST programming model'.
The WebGetAttribute attribute is applied to a service operation in addition to the OperationContractAttribute and associates the operation with a UriTemplate as well as the HTTP protocol Get verb.
Here is great post about REST / SOAP endpoints for a WCF service where you can see how to configure endpoints for both technologies and how to use WebGetAttribute.
I think this comes down to a question of granularity. An endpoint defines the entire contract you are exposing and a URI template is used to locate/manipulate a specific resource. If you are attempting to vary the output format for the consumer the WCF plumbing handles this for you(by appending the format to the uri, can't recall the specific string).

Categories