MTOM + basicHttpBinding - c#

I inherited a WCF service (1) configured with basicHttpBinding and it communicates with another WCF service (2) configured with basicHttpBinding. I was about to involve another WCF service (3), and in doing so I copied the binding configuration sections from (2) so (1) can now communicate with (3) as well. (1) to (2) is working just fine, but (1) to (3) bombs due to a configuration error.
The binding configuration of (2) has messageEncoding set to "Mtom", which from what I've read only applies to wsHttpBinding. When I leave messageEncoding="Mtom" in the config for (3), I get the configuration exception. If I take that out, or change it from "Mtom" to "Text", communication to (3) works just fine from (1).
WCF service (1) and (2) are both configured with basicHttpBinding, but both also have messageEncoding set to "Mtom".
I don't want to break something I don't fully understand, but I don't want to leave unnecessary (or incorrect) configuration in my web.config either. Is Mtom just being ignored in this case since both services are configured the same way and things are defaulting back to Text? Does Mtom apply in any way to basicHttpBinding?

basicHttpBinding can also support mtom, so your services used mtom. You can verify that if you put fiddler in the middle and see the payload.

Related

How to generate a WCF Client from the WSDL only for certain endpoints?

I have the WSDL of a large enterprise web service, which includes several endpoints, out of which I only intend to use one.
I tried generating the Service Client in Visual Studio by adding a Service Reference to the project. The issue is that due to the high number of endpoints available in the service, the generated client code in Reference.cs ended up having more than 1,400,000 lines, and Visual Studio seems to have a hard time handling it (IntelliSense often hangs, sometimes the whole VS crashes), and I imagine the build times will be longer too due to this.
And out of the hundreds of endpoints, I will only use one, and won't need the rest.
Is there a way to generate the Client code from the WSDL only for a certain endpoint, either with the Service Reference GUI of Visual Studio, or with svcutil? Or if not, is there some other straightforward way to do this?
I did not find any way to generate a client for a certain endpoint from the WSDL file. But you can call the service of an endpoint individually through the channel factory.Here is the demo:
EndpointAddress address = new EndpointAddress("http://localhost:8000/GettingStarted/CalculatorService1111");
BasicHttpBinding binding =new BasicHttpBinding();
ChannelFactory<ICalculator> factory = new
ChannelFactory<ICalculator>(binding, address);
ICalculator chanel = factory.CreateChannel();
You need to call that endpoint and pass in the address of that endpoint, define the corresponding binding, and then declare the channel factory. So you can call the method in the service. By using the channel factory you can call any endpoint of a service.

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.

CallBack Contract and Binding

I have my service on a web site. I try to run this example, first just the server part:
:What steps do I need to take to use WCF Callbacks?
But I get this message: "Contract requires Duplex, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it."
The Web.config file, doesn't have definitions such 'BasicHttpBinding'. It only has more general defitions. Do i have to add lines to it, or there is a more simple way. Many thanks.

Changing a WCF service from WSDualHHTP to NETTCP error

I have a WCF service set up as a WSDuallHTTP and everything works ok using this. The problem I have is that I need to be able to get the service to run as a non admin program. I know I can setup the WCF service so that an admin just has to grant right for the service to be able to run on a certain port range but If I can get rid of the need for admins altogether it would be much better.
Due to this I have read that the NETTCP binding both supports duplex and doesnt require admin rights to host the service. My first question is is this correct?
Also when I change the WSDualHTTP binding to a NETTCP binding I get the following error.
Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].
Here is the code thats failing:
string WCFHost = string.Format(WCF_URL, MainConfiguration.WCFCommunicationsURL,
MainConfiguration.WCFCommunicationsPort);
this.serviceHost = new ServiceHost(typeof(GX3WCFServerService), new Uri(WCFHost));
NetTcpBinding binding = new NetTcpBinding();
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
this.serviceHost.AddServiceEndpoint(typeof(IGX3WCFServerService), binding, "");
//the line above it the one throwing the exception
Please let me know if you need anymore information.
Worked out what the problem was. my WCFHost string began with HTTP:\ instead of NET.TCP:\

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