I am new to WCF. I'm trying to create a webservice from a client provided wsdl;
I'm having trouble changing some wcf generated wsdl entries to match the provided wsdl.
Here is my wsdl port name :
<wsdl:service name="MyService">
<wsdl:port name="BasicHttpBinding_IService" binding="i0:BasicHttpBinding_IService">
<soap:address location="http://localhost:53336/MyServiceApi.svc"/>
</wsdl:port>
</wsdl:service>
But I need change to
<wsdl:service name="MyServiceSoap">
<wsdl:port name="MyServiceSoap" binding="m:MyServiceSoap">
<soap:address location="http://localhost:53336/MyServiceApi.svc"/>
</wsdl:port>
</wsdl:service>
How do I that? Can someone please show me a simple solution?
I found a solution to setting port name.
like this:
<services>
<service name="MyServiceSoap">
<endpoint name="MyServiceSoap" address="" binding="basicHttpBinding" contract="IService" bindingNamespace="MyServiceSoap" bindingName="MyServiceSoap" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
then the wsdl port name will be that I want.
I added this attribute to my service implementation and that solved my problem:
[ServiceBehavior(Name = "MyServiceName")]
public class MyServiceClass : IServiceContract
{
// implementation code
}
Resulting WSDL:
<wsdl:service name="MyServiceName">
<wsdl:port name="MyServiceClass" binding="tns:MyServiceClass">
<soap:address location="http://localhost:52233/MyService.svc"/>
</wsdl:port>
</wsdl:service>
Related
I was unable to open the connection for my ServicHost. I have initially used the 8080 port it worked before.But now it is not working. I see some error (below) with my App.Conifg.Please let me know where the bug in.
This is a simple EmployeeWCF Demo app with the IEmployeeService interface and EmployeeService class.
App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<services>
<service name="EmployeeWCFService.EmployeeService" behaviorConfiguration="mexBehaviour">
<endpoint name ="httpBind" address="EmployeeService" binding="basicHttpBinding" contract="EmployeeWCFService.IEmployeeService" ></endpoint>
<endpoint name ="netTcpBind" address="EmployeeService" binding="netHttpBinding" contract="EmployeeWCFService.IEmployeeService" ></endpoint>
<endpoint name="mexBind" address="mex" binding="mexHttpBinding" contract="IMetadataExchange" ></endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:9090"/>
<add baseAddress="net.tcp://localhost:9093"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehaviour">
<serviceMetadata httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
ConsoleCode:
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(EmployeeWCFService.EmployeeService)))
{
host.Open();
Console.WriteLine("The connection host is opened at the time " + DateTime.Now);
Console.ReadLine();
}
}
}
Error I am Facing while opening WCF Servicehost:
Additional information: A binding instance has already been associated to listen URI 'http://localhost:9090/EmployeeService'. If two endpoints want to share the same ListenUri, they must also share the same binding object instance. The two conflicting endpoints were either specified in AddServiceEndpoint() calls, in a config file, or a combination of AddServiceEndpoint() and config.
There may be a typo in your configuration file. The second service endpoint ought to use NetTcpBinding instead of NetHttpBinding, which causes that the two serivce endpoints has the same listening uri address.
Feel free to contact me if the problem still exists.
Um quite new to WCF . I think I have messed up a bit. So this is what I did so far and I ve hosted my WCF service in IIS
First the Contracts
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using YangkeeServer.dto;
namespace YangkeeServer
{
public class Service1 : IService1
{
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "single")]
public YangkeeTrailerDTO getTrailor()
{
return new YangkeeTrailerDTO()
{
loanFrom = "heaven"
};
}
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "datum/{id}")]
public Test getName(string id)
{
return new Test()
{
Id = Convert.ToInt32(id) * 12,
Name = "Leo Messi"
};
}
}
}
and this is my web.config file
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="YangkeeServer.Service1">
<endpoint
contract="YangkeeServer.IService1"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/Service1.svc">
</endpoint>
</service>
<service name="YangkeeServer.Service2">
<endpoint
contract="YangkeeServer.IService2"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/Service2.svc">
</endpoint>
</service>
<service name="YangkeeServer.YangkeeTrailer">
<endpoint
contract="YangkeeServer.IYangkeeTrailor"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/YangkeeTrailor.svc">
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebHttp">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
and um using this urlhttp://localhost:7000/Service1.svc and um getting this error
Server Error in '/' Application.
When 'system.serviceModel/serviceHostingEnvironment/multipleSiteBindingsEnabled' is set to true in configuration, the endpoints are required to specify a relative address. If you are specifying a relative listen URI on the endpoint, then the address can be absolute. To fix this problem, specify a relative uri for endpoint 'http://localhost:7000/Service1.svc'.
can any one tell me where did I do wrong? Thank you in advance.
Set the service endpoint address to just the service filename (this is the relative part):
address="Service1.svc"
or set the address to blank for each endpoint (I don't think its needed when hosting in the development environment or in IIS)
address=""
See this answer to another question
The relevant part is:
the virtual directory (in IIS) where your *.svc file exists defines your service endpoint's address.
To fix this error, I added... listenUri="/" ... to the service endpoint.
Example:
<service name="_name_">
<endpoint address="http://localhost:_port_/.../_servicename_.svc"
name="_servicename_Endpoint"
binding="basicHttpBinding"
bindingConfiguration="GenericServiceBinding"
contract="_contractpath_._contractname_"
listenUri="/" />
</service>
MSDN: Multiple Endpoints at a Single ListenUri
This works for me:
1. Insert this lines inside service:
<host>
<baseAddresses>
<add baseAddress="http://localhost:7000/Service1.svc" />
</baseAddresses>
</host>
2. Set the value of address as bellow:
address=""
The full code:
<service name="YangkeeServer.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:7000/Service1.svc" />
</baseAddresses>
</host>
<endpoint
contract="YangkeeServer.IService1"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="">
</endpoint>
</service>
I'm getting this
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
when trying to access the service from my browser. Here is my config.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<!-- Note: the service name must match the configuration name for the service implementation. -->
<service name="WcfServiceLibrary.Service1" behaviorConfiguration="MyServiceTypeBehaviors" >
<!-- Add the following endpoint. -->
<!-- Note: your service must have an http base address to add this endpoint. -->
<endpoint contract="WcfServiceLibrary.Service1" binding="basicHttpBinding" address="http://localhost/service1" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="http://localhost/service1/mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- Add the following element to your service behavior configuration. -->
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost/service1" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
When I type http://localhost/service1 in the web browser I get the 404. But if I remove the app.config below and just simpley do this in the code behind
string serviceUrl = "http://localhost/service1";
Uri uri = new Uri(serviceUrl);
host = new ServiceHost(typeof(Service1), uri);
host.Open();
All works well... Any ideas? Seems simple enough.
I think you are missing the host element under your services:
<service name="WcfServiceLibrary2.Service1">
<host>
<baseAddresses>
<add baseAddress = "http://localhost/service1" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary2.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
Service host does not need URL then.
static void Main(string[] args)
{
var host = new ServiceHost(typeof(Service1));
host.Open();
Console.WriteLine("Host running");
Console.ReadLine();
}
You can show http://localhost/service1?Wsdl in the browser but mex only works with add service reference or WCFTestClient (C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE) because you will get the HTTP Bad Request error which comes from the fact that the browser issues an HTTP GET request where the contents of the message are in the HTTP headers, and the body is empty.
This is exactly what the WCF mexHttpBinding is complaining about.
I have two classes implementing a contract at a service which are consumed from a factory on the client like shown below.
[ServiceContract]
public interface MyInterface {
void DoSomething()
}
public class A : MyInterface {
public void DoSomething(){
"Hi I'm A"
}
}
public class B : MyInterface {
public void DoSomething(){
"Hi I'm B"
}
}
public class MyFactory <TMyInterface> {
void DoSomething(){
TMyInterface.DoSomething()
}
}
The client must remain the same. My question is how can I choose at the server side which implementation of MyInterface to use, by passing the type parameter using .config file in WCF
I read other post but I don't understand yet :(
It is possible to do it, and there are a few ways to do it.
One possibility is to create a "routing" service which will contain the "public" address which the client always talks to. This routing service can then, based on some configuration, redirect the call to the appropriate "real" service.
Another way is to actually have a process which starts both services, but their addresses are defined in config. If you use the same binding and the same contract (which is the case), then you can "flip-flop" the service address when you want to change the service which will receive the calls from the client. For example, this configuration directs the requests to the endpoint at "http://machine-name:8000/Service" to service A. Notice that, since you define service hosts for both services, you actually need to have a base address for service B as well - in this case I used named pipes, which cannot be accessed via different machines.
<system.serviceModel>
<services>
<service name="A">
<host>
<baseAddresses>
<add baseAddress="http://machine-name:8000/Service"/>
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding" contract="MyInterface" />
</service>
<service name="B">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/ServiceBackup"/>
</baseAddresses>
</host>
<endpoint address="" binding="netNamedPipeBinding" contract="MyInterface" />
</service>
</services>
</system.serviceModel>
when you want to change the address for B, you'd then swap the addresses.
<system.serviceModel>
<services>
<service name="A">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/ServiceBackup"/>
</baseAddresses>
</host>
<endpoint address="" binding="netNamedPipeBinding" contract="MyInterface" />
</service>
<service name="B">
<host>
<baseAddresses>
<add baseAddress="http://machine-name:8000/Service"/>
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding" contract="MyInterface" />
</service>
</services>
</system.serviceModel>
The hosting program would look like this:
public static void HostServices()
{
ServiceHost hostA = new ServiceHost(typeof(A));
ServiceHost hostB = new ServiceHost(typeof(B));
hostA.Open();
hostB.Open();
Console.WriteLine("Press ENTER to close");
Console.ReadLine();
hostA.Close();
hostB.Close();
}
Now, if your services are hosted in IIS (webhost), then it's a little harder. Since the "normal" activation requires a .svc file to be part of the endpoint address, and each .svc file is associated with a single class, the address for A would be something like http://machine-name/services/a.svc while the address for B would be something like http://machine-name/services/b.svc. So what you'd need to do in this case is to create a custom ServiceHostFactory, and use the ASP.NET Routes integration to create a .svc-less URL for your service. Then you'd use something similar to the previous example to decide which service will be activated.
I've derived my own clientbase class. I have a winforms app (client) and the server (windows svc). In the app.config file, I have the following values:
<system.serviceModel>
<services>
<service name = "xtest">
<endpoint
address = "net.pipe://localhost/test"
binding = "netNamedPipeBinding"
contract = "ITest"
/>
</service>
</services>
</system.serviceModel>
This is the same as my server. What is amiss?
Thanks
On the client you need to have a <client> element, not a <services/service>. You'd have something like the config below.
<system.serviceModel>
<client>
<endpoint address="net.pipe://localhost/test"
binding="netNamedPipeBinding"
contract="ITest" />
</client>
</system.serviceModel>