How to setup a self hosted WCF service - c#

I have been through WCF concepts, read many and created SELF HOSTED service.
I added library to solution "CommunicationLibrary" which contains:
[ServiceContract]
interface ICommunication
{
[OperationContract]
string message();
}
and
public class Communication: ICommunication
{
public string message()
{
return "WCF Method Accessed";
}
}
then I added console project to host it "WCFCommunicationHosting" which contains
class WcfHost
{
static void Main(string[] args)
{
Uri baseadd = "sasas";
ServiceHost sh = new ServiceHost(typeof(CommunicationLibrary.Communication), baseadd);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
sh.Description.Behaviors.Add(smb);
sh.Open();
Console.WriteLine("Host Running");
}
}
now I don't understand that what to pass in baseAdd? I saw many examples like this CodeProject article but I don't understand that why and how they are passing localhost://.

Here is a working example. Its in vb.net, but you should get the idea of how/what is implemented.
Your service address is the address that you will specify in the connection / binding properties on your client that will consume the service. This is the address where it will find and communicate with your web service.
Dim LocalIpAddress as string = "your pc ip"
Dim tcp_port as string = "the port you want to use"
Dim myServiceAddress As New Uri("http://" & localIpAddress & ":" & tcp_port & "/" & servicename)
myservicehost = New ServiceHost(GetType(yourwcfservicemethodsclass), myServiceAddress)
Dim BasicBinding As New BasicHttpBinding
BasicBinding.MaxReceivedMessageSize = 2147483647
myservicehost.AddServiceEndpoint(GetType(Iyourwcfservicemethodsclass), BasicBinding, myServiceAddress)
' Enable metadata publishing.
Dim smb As New ServiceMetadataBehavior()
smb.HttpGetEnabled = True
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15
myservicehost.Description.Behaviors.Add(smb)
myservicehost.Open()

Related

Wcf auto-host que permite conexiones a través de Internet

I need to create a self-hosted WCF service, which allows access through the internet, and it throws this error at me ”System.ServiceModel.EndpointNotFoundException: There was no end listening on http://fabianwesling.dynu.com:28620/HostManager/Service that could accept the message. The cause is usually an incorrect SOAP address or action. ”
can someone help me what is the mistake I am making, I have opened the ports on the router, router firewall and Windows and deactivate the antivirus
… I show you what I have done.
Service
[ServiceContract()]
public interface IService
{
[OperationContract()]
int SumValues(int value1, int value2);
}
public class Service : IService
{
public static void Configure(ServiceConfiguration config)
{
config.Description.Behaviors.Add(new ServiceMetadataBehavior
{
HttpGetEnabled = true
});
config.Description.Behaviors.Add(new ServiceDebugBehavior
{
IncludeExceptionDetailInFaults = true,
});
config.EnableProtocol(new BasicHttpBinding() );
config.EnableProtocol(new NetTcpBinding());
}
public int SumValues(int value1, int value2)
{
return value1 + value2;
}
}
Run server local Host
Uri http_Uri = new Uri("http://192.168.1.100:28620/HostManager/Service");
Uri netTCP_Uri = new Uri("net.tcp://192.168.1.100:28621/HostManager/Service");
host = new ServiceHost(typeof(HostManager.Services.Service), http_Uri,netTCP_Uri );
host.Open();
Run server to access from internet
Uri http_Uri = new Uri("http://fabianwesling.dynu.com:28620/HostManager/Service");
Uri netTCP_Uri = new Uri("net.tcp://fabianwesling.dynu.com:28621/HostManager/Service");
host = new ServiceHost(typeof(HostManager.Services.Service), http_Uri);
host.Open();
client local connection
EndpointAddress uri = new EndpointAddress("http://192.168.1.100:28620/HostManager/Service");
ServiceReference1.ServiceClient service = new ServiceReference1.ServiceClient("BasicHttpBinding_IService", uri);//http binding
//EndpointAddress uri = new EndpointAddress("net.tcp://192.168.1.100:28621/HostManager/Service");
//ServiceReference1.ServiceClient service = new ServiceReference1.ServiceClient("NetTcpBinding_IService", uri); ///net-tcp binding
var result = service.SumValues(GetNumber(), GetNumber());
client connection through internet
//http binding
EndpointAddress uri = new EndpointAddress(" http://fabianwesling.dynu.com/:28620/HostManager/Service");
ServiceReference1.ServiceClient service = new ServiceReference1.ServiceClient("BasicHttpBinding_IService", uri);
//net-tcp binding
//EndpointAddress uri = new EndpointAddress(" http://fabianwesling.dynu.com/:28620/HostManager/Service");
//ServiceReference1.ServiceClient service = new ServiceReference1.ServiceClient("NetTcpBinding_IService", uri);
var result = service.SumValues(GetNumber(), GetNumber());
Modify domain name to IP address:
EndpointAddress uri = new EndpointAddress(" http://xxx.xxx.xxx.xxx/:28620/HostManager/Service");
ServiceReference1.ServiceClient service = new ServiceReference1.ServiceClient("BasicHttpBinding_IService", uri);
var result = service.SumValues(GetNumber(), GetNumber());
Ensure that the IP address is an IP address on the public network.

wsHttpBinding workarounds in .NET Core

I am looking for a dotnet core WCF wsHttpBinding workaround.
I am aware that .net core WCF implementation currently does not support wsHttpBinding (see support matrix here https://github.com/dotnet/wcf/blob/master/release-notes/SupportedFeatures-v2.1.0.md)
I'm integrating with a legacy third party service that appears to only support wsHttpBinding. Our tech stack is .net core, so I cannot revert to the full version of .net framework or mono variant.
The question is whether it's possible to use the service via custom bindings? I am hoping that there is a workaround that maybe isn't fully functional, but at least allows me to consume the service.
var cBinding = new CustomBinding();
var textBindingElement = new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.Soap12WSAddressing10
};
cBinding.Elements.Add(textBindingElement);
var httpBindingElement =
new HttpsTransportBindingElement
{
AllowCookies = true, MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue,
};
cBinding.Elements.Add(httpBindingElement);
var myEndpoint = new EndpointAddress("https://..../Service.svc/wss");
using (var myChannelFactory = new ChannelFactory<ISearch>(cBinding, myEndpoint))
{
myChannelFactory.Credentials.UserName.UserName = "...";
myChannelFactory.Credentials.UserName.Password = "...";
ISearch client = null;
try
{
client = myChannelFactory.CreateChannel();
var result = client.Find(new Search("Criteria")).Result;
((ICommunicationObject)client).Close();
myChannelFactory.Close();
}
catch (Exception ex)
{
(client as ICommunicationObject)?.Abort();
}
}
Client gets created and a call is made to the service, but it fails because:
Message = "The message could not be processed. This is most likely because the action '' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between binding
Forget it, they are not completely compatible with Core. Under some specified case, there may be a basic call to WsHttpBinding. You could refer to the following example.
Server.
Uri uri = new Uri("http://localhost:11011");
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.None;
using (ServiceHost sh=new ServiceHost(typeof(MyService),uri))
{
sh.AddServiceEndpoint(typeof(IService), binding, "");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb==null)
{
smb = new ServiceMetadataBehavior()
{
};
sh.Description.Behaviors.Add(smb);
}
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
sh.Opened += delegate
{
Console.WriteLine("Service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("Service is clsoed");
};
sh.Open();
Client(auto-generated)
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.WSHttpBinding_IService))
{
System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
result.Elements.Add(textBindingElement);
System.ServiceModel.Channels.HttpTransportBindingElement httpBindingElement = new System.ServiceModel.Channels.HttpTransportBindingElement();
httpBindingElement.AllowCookies = true;
httpBindingElement.MaxBufferSize = int.MaxValue;
httpBindingElement.MaxReceivedMessageSize = int.MaxValue;
result.Elements.Add(httpBindingElement);
return result;
}
Invocation.
ServiceReference1.ServiceClient client2 = new ServiceReference1.ServiceClient();
try
{
var res = client2.SayHelloAsync();
Console.WriteLine(res.Result);
}
catch (Exception)
{
throw;
}
While in most cases it is impossible to call WCF service created by WsHttpBinding.
Officials also have no intention of continuing to support plan for wshttpbinding.
Here are related discussions.
https://github.com/dotnet/wcf/issues/31
https://github.com/dotnet/wcf/issues/1370

wsHttpBinding with username password

I am trying to set wsHttpBinding with username / password.
The problem that I've ran into is how to set username / password?
I've set this:
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
But where is the setting for username / password?
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
Type contractType = typeof(ITest);
Type serviceType = typeof(Test);
Uri httpUri = new Uri("http://localhost:8083/Test2");
ServiceHost myServiceHost = new ServiceHost(serviceType, httpUri);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
myServiceHost.Description.Behaviors.Add(smb);
myServiceHost.Open();
Code:
namespace ConsoleApplication1
{
[ServiceContract]
interface ITest
{
[OperationContract]
string Ping();
}
}
namespace ConsoleApplication1
{
class Test : ITest
{
public string Ping()
{
return "Pong - it works!";
}
}
}
By default WCF uses Windows users to authenticate. But you can plugin your own custom validator.
You need to create your class inherited from UserNamePasswordValidator and then tell WCF to use it:
myServiceHost.Description.Behaviors.Find<ServiceCredentials>().UserNameAuthentication
.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
myServiceHost.Description.Behaviors.Find<ServiceCredentials>().UserNameAuthentication
.CustomUserNamePasswordValidator = new MyCustomValidator();
See also this example and official MSDN documentation.

WCF EndpointNotFoundException when running as NetworkService

I have a net.Pipe WCF service that is hosted by IIS (right now, in my VS2010):
(Global.asax):
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
ServiceHost svcHost = new ServiceHost(typeof(DoSomethingService), new Uri("net.pipe://localhost/helloworld"));
var serviceBinding = new NetNamedPipeBinding { MaxReceivedMessageSize = int.MaxValue, MaxConnections = 2048 };
var sect = new NamedPipeTransportSecurity { ProtectionLevel = ProtectionLevel.EncryptAndSign };
var sec = new NetNamedPipeSecurity { Mode = NetNamedPipeSecurityMode.Transport, Transport = sect };
serviceBinding.Security = sec;
svcHost.AddServiceEndpoint(typeof(IDoSomethingContract), serviceBinding, "");
svcHost.Open();
}
I have a console app client:
static void Main(string[] args)
{
var factory = new ChannelFactory<IDoSomethingContract>();
var defaultCredentials = factory.Endpoint.Behaviors.Find<ClientCredentials>();
factory.Endpoint.Behaviors.Remove(defaultCredentials);
factory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
factory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
var serviceBinding = new NetNamedPipeBinding { MaxReceivedMessageSize = int.MaxValue, MaxConnections = 2048 };
var sect = new NamedPipeTransportSecurity { ProtectionLevel = ProtectionLevel.EncryptAndSign };
var sec = new NetNamedPipeSecurity { Mode = NetNamedPipeSecurityMode.Transport, Transport = sect };
serviceBinding.Security = sec;
var ep = new EndpointAddress("net.pipe://localhost/helloworld");
factory.Endpoint.Binding = serviceBinding;
var love = factory.CreateChannel(ep);
Console.WriteLine(love.Do());
Console.ReadKey();
}
Now everything works great when I run this as a user principal (and so I can use a PrincipalPermission inside my operation).
However, if I create myself a 'Network Service' command line prompt (using psexec), and try to run the client (with the service running, obviously), I get the EndpointNotFoundException exception.
Is there anything I need to do for Network Service to see my named pipe?
May be following articles useful for you
http://www.aspfree.com/c/a/asp-net/developing-a-wcf-service-library-and-hosting-it-as-wcf-web-service-using-vs2k8/
http://msdn.microsoft.com/en-us/library/dd728288%28v=vs.110%29.aspx
I was considering deleting this, but since somebody actually commented - I found the answer here:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/fcb7254a-15b5-4be4-bf67-34d500bdce2d/wcf-netpipe-endpoint-not-found-exception-whitout-elevated-user-rights-uac-enabled?forum=wcf
Basically, since I was running my dev server as my own account, the service was published in Session namespace. Once I published this on real IIS as Network Service, it was visible in the Global Namespace, so I could see it.

There was no endpoint listening

When I try to call the method in the WCF host I get this error:
There was no endpoint listening at net.pipe://localhost/PipeReverse
that could accept the message. This is often caused by an incorrect
address or SOAP action. See InnerException, if present, for more
details.
I have a class that starts the WCF host:
public class ProcessUnderMouseServer
{
public ProcessUnderMouseServer()
{
using (host = new ServiceHost(
typeof(PrcoessUnderMouse),
new Uri[]
{
new Uri("net.pipe://localhost")
}))
{
host.AddServiceEndpoint(
typeof(IPrcoessUnderMouse),
new NetNamedPipeBinding(),
"PipeReverse");
host.Open();
}
}
}
this class is in a different library project than the consuming project
Then I try to consume it like this:
ProcessUnderMouseServer ProcessUnderMouseServer = new ProcessUnderMouseServer();
ChannelFactory<IPrcoessUnderMouse> pipeFactory =
new ChannelFactory<IPrcoessUnderMouse>(
new NetNamedPipeBinding(),
new EndpointAddress(
"net.pipe://localhost/PipeReverse"));
IPrcoessUnderMouse pipeProxy = pipeFactory.CreateChannel();
string str = Console.ReadLine();
Console.WriteLine("pipe: " + pipeProxy.GetProcessUnderMouse());
Shouldn't
host.AddServiceEndpoint(typeof(IPrcoessUnderMouse),new NetNamedPipeBinding(), "PipeReverse");
be sufficient to add the end point? why it says that no endpoint listening at net.pipe://localhost/PipeReverse ??

Categories