WCF WebInvoke problem getting WSDL - wcf

i got a webservicedefinition like this:
[OperationContract]
[FaultContract(typeof(Exception))]
[WebInvoke(ResponseFormat = WebMessageFormat.Xml,
BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Xml)]
SearchResponse SearchXML(SearchRequest req);
and a Service config like this:
<service name="SearchEngine.SearchService" behaviorConfiguration="HTTPGetBehavior">
<endpoint address="SearchEngine.SearchService" behaviorConfiguration="ajaxBehavior" binding="webHttpBinding" contract="SearchEngine.ISearchInterface" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8800/SearchService" />
</baseAddresses>
</host>
</service>
and i want to get the WSDL file, which should be possible with a HTTP-GET request like this:
http://localhost:8800/SearchService?wsdl
But all iam getting is a "method not allowed message by the wcf-service"
What am i doing wrong? I want the WSDL information to show the structure of request and response to an external client ( so that he can prepare his function calls )
Thanks

Well, if I read the binding correctly, you're using the "webHttpBinding" which is a REST interface.
REST does not have anything like the WSDL file - that's a SOAP thing.
REST is considered easier to use and simpler to understand - but it doesn't have the amount of metadata that a typical SOAP web service will have.
So basically, if you stick with REST (webHttpBinding), you can't have a WSDL - you have to find another way to communicate your service methods exposed and the possible parameters they expect.
There seem to be efforts under way to come up with something similar to a WSDL for REST called Web Application Description Language (WADL) but I don't know how far that effort has come, and as far as I know, the WCF REST starter kit doesn't support any of that just yet.
Check out some links for WADL:
Sun Web Application Description Language Spec
WADL REST API description language getting some attention
Do we need WADL?
Does REST need a WSDL?
Marc

Related

Asp.NET Core 2.2 WCF Warning: Policy

I'm trying to add wsdl using WCF. But at first I get an warning like this;
enter image description here
Here is the details:
The following Policy Assertions were not Imported:
XPath://wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:binding[#name='zz_binding_SOAP12']
Assertions:
<saptrnbnd:OptimizedXMLTransfer xmlns:saptrnbnd='http://www.sap.com/webas/710/soap/features/transportbinding/'>..</saptrnbnd:OptimizedXMLTransfer>
<sapattahnd:Enabled xmlns:sapattahnd='http://www.sap.com/710/features/attachment/'>..</sapattahnd:Enabled>
The following Policy Assertions were not Imported:
XPath://wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:binding[#name='zz_binding']
Assertions:
<saptrnbnd:OptimizedXMLTransfer xmlns:saptrnbnd='http://www.sap.com/webas/710/soap/features/transportbinding/'>..</saptrnbnd:OptimizedXMLTransfer>
<sapattahnd:Enabled xmlns:sapattahnd='http://www.sap.com/710/features/attachment/'>..</sapattahnd:Enabled>
The optional WSDL extension element 'Policy' from namespace 'http://schemas.xmlsoap.org/ws/2004/09/policy' was not handled.
XPath: //wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:portType[#name='zz_test_web_structure']/wsdl:operation[#name='ZzTestWebService']
The optional WSDL extension element 'Policy' from namespace 'http://schemas.xmlsoap.org/ws/2004/09/policy' was not handled.
XPath: //wsdl:definitions[#targetNamespace='urn:sap-com:document:sap:soap:functions:mc-style']/wsdl:portType[#name='zz_test_web_structure']
I still can't run the wcf service after adding it. Does anyone know about this?
Microsoft WCF Web Service Reference Provider tool based on the Mex service endpoint, namely metadata exchange service endpoint instead of the Web service definition language(WSDL page).
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="basicHttpBinding" contract="WcfService1.IService1" bindingConfiguration="mybinding"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
Or,
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
If you prefer to generate a client proxy class by using WSDL, you could try the SVCUtil.exe tool.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/servicemodel-metadata-utility-tool-svcutil-exe
All the above ways can generate a client proxy class.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
Besides, In WCF4.5 there is a new feature called SingleWSDL, which contains the whole WSDL with the related schema. It could be consumed perfectly by a third-party system.
What is the difference between ?wsdl and ?singleWsdl parameters
https://learn.microsoft.com/en-us/dotnet/framework/wcf/whats-new
Feel free to let me know if there is anything I can help with.

regarding mex endpoints in wcf

here is one sample of mex endpoints
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
but i have seen people write mex endpoints like
<endpoint address="net.tcp://localhost:1645/ChatServer/mex"
binding="mexTcpBinding"
contract="IMetadataExchange"/>
so tell me why and when one should write mex endpoint like above one.
just compare my two endpoints and see the difference that first one address attribute has
the word called "mex" but second one has url.
so my question is "when people has to give a url to address attribute of mex endpoints?".
Another question is "Does mex address url always should have /mex word at the end of url?".
if i give url like net.tcp://localhost:1645/ChatServer/ or net.tcp://localhost:1645/ChatServer without mex word then service will not be discoverable?
what is the significiant of /mex word??
the first one will expose metadata over http and second one will do it over the TCP . It is used to support the platforms, WCF is made for supporting multiple platform.
you can make any url to expose metadata. it is not necessary to follow the convention above.
mex is just more good practice to make it metadata just same like url+mex .
here is an url which will give an overview
http://www.danrigsby.com/blog/index.php/2008/05/27/wcf-metadata/

WCF service versioning with single SVC

Due to some certain requirement, I've got to use a single svc for multiple service versions. I've separated the interface contract for each version using different namespaces. I have only one class (partial) implementing all the service versions.
My code is as below:
namespace Application.V1
{
[ServiceContract(Namespace = "http://google.com/ApplicationService/v1.0", Name = "IMathService")]
public interface IMathService
}
namespace Application.V2
{
[ServiceContract(Namespace = "http://google.com/ApplicationService/v2.0", Name = "IMathService")]
public interface IMathService
}
The Application/MathServiceV1.cs file:
public partial class MathService : V1.IMathService { }
The Application/MathServiceV2.cs file:
public partial class MathService : V2.IMathService { }
The Application/MathService.cs file:
public partial class MathService {}
I've added the following in the service web.config:
<service behaviorConfiguration="ServiceBehavior" name="Application.MathService">
<endpoint address="V1" binding="wsHttpBinding" contract="Application.V1.IMathService" />
<endpoint address="V2" binding="wsHttpBinding" contract="Application.V2.IMathService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
I have a file MathService.svc with the following:
<%# ServiceHost Service="Application.MathService, Application"
Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"%>
If I generate a proxy with the address http://localhost:8000/MathService.svc the client endpoints are generated as below:
<client>
<endpoint address="http://localhost:8000/MathService.svc/V1"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMathService"
contract="MathService.IMathService" name="WSHttpBinding_IMathService">
</endpoint>
<endpoint address="http://localhost:8000/MathService.svc/V2"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMathService1"
contract="MathService.IMathService1" name="WSHttpBinding_IMathService1">
</endpoint>
</client>
My concern is that the client endpoint address is generated with MathService.svc/V1 but I'd like to see V1/MathService.svc.
If i browse the service with the address http://localhost:8000/MathService.svc/V1 i am getting HTTP 400 Bad Request error.
Any suggestions?
Regarding your 400 bad request error - you probably dont have MEX enabled, so making a request without a payload makes no sense to the service.
Here is a question about enabling MEX:
WCF How to enable metadata?
Either enable MEX - or use a proper service consumer to call your service.
Regarding your addressing - you cannot do what you want to do with WCF alone. Because you are using IIS hosted WCF (I assume this because you are using an SVC file), your HTTP request must be directed to the location of your SVC file, and anything after that (/V1 for example) is used to locate the appropriate endpoint. This is just how it works in IIS. Putting the /v1/ BEFORE the file name (MathService.asmx) tells IIS to look for a folder called /v1/ before attempting to locate a file named MathService.asmx - obviously it wont find anything there!
However, you may be able to install a URL rewriter in your Web.config to redirect your preferred URI to the one mentioned above.
Here is some documentation on Url rewriting in asp.net:
http://www.iis.net/learn/extensions/url-rewrite-module/iis-url-rewriting-and-aspnet-routing

What Service name does one use for Workflow WCF Services (XAMLX)

I am trying to figure out how to provide endpoints etc to a WF Service that I created (MyFoo.xamlx). Typically when you create a Service you need to have the Service name="" reflect the type of service you've created? ie by filling out something like this:
<Service name="MyNameSpace.Foo" behaviorConfiguration="myFooBehaviorConfig">
This works in a typical .svc scenario and I can get that working fine. Only how does one map this concept across to a .xamlx service? In that if I have Foo.xamlx putting that inside the Service name doesn't work - or doesn't appear to work (as in no metadata is enabled).
If i then remove the behaviorConfiguration attribute from the Service and also remove the myFooBehaviorConfig from the <behavior/> tag - in that it essentially then takes on more of a global setting for the web config - boom! I can see the .xamlx exposed methods/operations?
<serviceBehaviors>
<behavior name="foo" >
vs
<serviceBehaviors>
<behavior >
At first this is great, no effort required but at the same time I don't want devs to access HTTP endpoints or netpipe for that matter. I only want them to come in through net.tcp port I specify. In order to do that I need to match the <Service name=""/> to the xamlx somehow?
I've also tried using the trick of creating an empty .svc file and then pointing to the xamlx that way (so that the devs always assume its a .svc and not a .xamlx)
<%# ServiceHost Language="C#" Debug="true" Service="ActivityHubService.xamlx" Factory="System.ServiceModel.Activities.Activation.WorkflowServiceHostFactory" %>
Again, if I remove naming the behavior etc this also works via foo.svc ..but i just can't seem to crack the whole matching a <service> with a freakin xamlx!! :) hehe.
Frustrating..
Anyone an expert in this space?
I'm gonna give this one to GuerreroTook as although the answer he gave was partially in the same area of right it did however spark a moment of "yeah maybe its that simple.." thinking..
The solution was this:
<services>
<service name="ActivityHubService" behaviorConfiguration="foo">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="netTCPStreamedBinding" contract="IService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://synapse.hub.security:669/SynapseHubSecurity/ActivityHubService" />
</baseAddresses>
</host>
</service>
</services>
Then inside a service i called PingService.svc I put this:
<%# ServiceHost Language="C#" Debug="true" Service="ActivityHubService.xamlx" Factory="System.ServiceModel.Activities.Activation.WorkflowServiceHostFactory" %>
That seemed to have done the trick!! :)
Not sure why but i swore I did this like 3x and it failed..but...i am also in need of sleep..
Hopefully this will help others in the same jam down the track.
Based on what you ask, I understand that you need to expose a WF Workflow as a WCF service and you want client to call directly WF through WCF infrastructure, is that right?
The problem you facing is that you need to provide the full qualified name of the class in order to the factory to find and activated your WF workflow. If you have a typical WP project inside VisualStudio the Full Qualified Name is the name of the project + the class name, try with this.
When you build your workflow xaml file the compile will generate a class that hold and the code and logic, and following the same behavior of the xaml (WPF and Silverlight) compiler the name of the class will be the same of the file (.xamlx)

WCF client config: centralized endpoint address

i've a WCF client wicht refers to multiple services hosted in the same machine. like this example
<client>
<endpoint address="net.tcp://localhost:8731/TrackingService" binding="netTcpBinding" ...
</endpoint>
<endpoint address="net.tcp://localhost:8731/CommonService" binding="netTcpBinding"...
</endpoint>
</client>
is it possible to modify my app.config in order to keep the
net.tcp://localhost:8731
part of endpoint address in a different variable, so when i'll deploy i have to change it once?
Maybe a programmatically clever way to do this? My only need is to change "address:port".
Thank you in advance
No, unfortunately, on the client side, there's nothing like a <baseAddress> like on the server side, which you can set globally.
Each endpoint declaration must have the entire, complete URL in it, I'm afraid.
Marc
You can always programmatically create your client and read the address from a normal appconfig value. Like this
MyClient client=
new MyClient(new BasicHttpBinding(), new EndpointAddress(ConfigurationManager.AppSettings.Get("ServiceAddress");)