I have my WCF in my service References and when I run my WCF at the same time as I run my WPF using visual studio run multi projects then it all works fine, however I am now connecting multiple clients and if they start at the same time before no data is entered then it works. If one starts enters data then the other starts then the entered data is wiped. I have tried having it so it will start by running a host from my WPF. Unfortunately I get an error saying httpGetEnabled needs to be false, if this is false then I cannot update my service reference as it says there is an access issue. The code I have used for trying to run the host is.
try
{
ServiceHost host;
Service1.Service1Client service = new Service1.Service1Client();
string baseAddress = "http://localhost:59849/Service1.svc";
host = new ServiceHost(typeof(Service1.Service1Client));
host.AddServiceEndpoint(typeof(Service1.IService1),new BasicHttpBinding(), baseAddress);
host.Open();
wcfHostId = wcf.generateId();
textBox5.Text = "" + wcfHostId;
button5.IsEnabled = false;
}
catch (Exception ex)
{
MessageBox.Show("Error = " + ex.Message);
}
Edit
So basically what I was saying is when I was self hosting a WPF and a new client connected it was wiping all the variables stored inside the service. And I was enquiring was it because of the way I was hosting the service?
The error was the way I was trying to discover the WCF and didn't add a discovery endpoint.
host.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
host.AddServiceEndpoint(new UdpDiscoveryEndpoint());
needed to be added to the host part and the client code in the end was
var ep = "http://" + System.Net.Dns.GetHostName() + ":8732/DatabaseTransfer/Service1/";
var binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.None;
binding.SendTimeout = new System.TimeSpan(0, 1, 30);
ChannelFactory<IService1> wcfFactory = new ChannelFactory<IService1>(binding, new EndpointAddress(ep));
IService1 wcf = wcfFactory.CreateChannel();
Related
I have been working with this solution where A client application is supposed to access WCF service via Relay.
I have followed this tutorial and was able to access WCF service hosted in console app with client console app.
What I want to achieve is, To access WCF service hosted in local machine via a function app.
So I migrated the code which i did in client console app as shown here to the azure function app.
The client console app had a config file as shown here
I have 2 doubts
I have two doubts.
1) I can not understand how to define endpoint in azure function app which was defined in App.Config file in case of console app as below.
<client>
<endpoint name="RelayEndpoint"
contract="Microsoft.ServiceBus.Samples.IEchoContract"
binding="netTcpRelayBinding"/>
</client>
2) Is there any way to dynamically define endpoint right in the code of function app?
log.Info("C# HTTP trigger function processed a request.");
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;
string serviceNamespace = "MyTestRelay";
string sasKey = "mpQKrfJ6L4Ftdsds2v6Leg3X0e9+Q8MOfjxwghj7xk2qSA=";
Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "EchoService");
TransportClientEndpointBehavior sasCredential = new TransportClientEndpointBehavior();
sasCredential.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", sasKey);
DynamicEndpoint dynamicEndpoint = new DynamicEndpoint(ContractDescription.GetContract(typeof(IEchoContract)), new WSHttpBinding() );
//I AM GETTING ERROR IN Below Line
ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
channelFactory.Endpoint.Behaviors.Add(sasCredential);
IEchoChannel channel = channelFactory.CreateChannel();
channel.Open();
Console.WriteLine("Enter text to echo (or [Enter] to exit):");
string input = Console.ReadLine();
while (input != String.Empty)
{
try
{
Console.WriteLine("Server echoed: {0}", channel.Echo(input));
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
input = Console.ReadLine();
}
channel.Close();
channelFactory.Close();
Can anyone suggest how to work with this?
The syntax for creating bindings in code maps to the XML in app.config and you can use like so:
var endpoint = new EndpointAddress(serviceUri);
var binding = new NetTcpRelayBinding()
{
// Example properties that might be in your app.config
ReceiveTimeout = TimeSpan.FromMinutes(2),
SendTimeout = TimeSpan.FromMinutes(2),
};
var channelFactory = new ChannelFactory<IEchoChannel>(binding, endpoint);
No idea what's going on. Simple application hosted service. Ran fine on server A. Copied everything over to server B...and suddenly won't launch.
Any tips? Ideas? I'll happily provide more info. Thanks for any help.
Error message:
The communication object, System.ServiceModel.ServiceHost, cannot be
used for communication because it is in the Faulted state.
Code (FAILS AT HOST.OPEN()_
static void Main(string[] args)
{
try
{
Uri baseAddress = new Uri("http://localhost:8080/Brp");
Uri mexUri = new Uri("http://localhost:8080/Brp/mex");
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(BBService), baseAddress))
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetUrl = mexUri;
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
BasicHttpBinding binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = int.MaxValue;
binding.Security.Mode = BasicHttpSecurityMode.None;
host.AddServiceEndpoint(typeof(IBService), binding, "");
// Enable metadata publishing.
var behavior = host.Description.Behaviors.Find<ServiceDebugBehavior>();
behavior.IncludeExceptionDetailInFaults = true;
host.Open();
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
} catch (Exception excep)
{
writeMessage("EXCEPTION!!! - " + excep.Message);
}
In case anyone else runs into this do: Right-click -> Run as administrator
You have to follow certain rules while working with Message contract
1. When using Message contract type as parameter, Only one parameter can be used in servicie Operation
[OperationContract]
void SaveEmployeeDetails(EmployeeDetails emp);
2. Service operation either should return Messagecontract type or it should not return any value
[OperationContract]
EmployeeDetails GetEmployeeDetails();
3. Service operation will accept and return only message contract type. Other data types are not allowed.
[OperationContract]
EmployeeDetails ModifyEmployeeDetails(EmployeeDetails emp);
Note: If a type has both Message and Data contract, service operation will accept only message contract.
I've researched this for a day now and am turning to you experts here for your advice.
I have REST service that is the main IIS hosted service.
This service needs to interface with a 32-bit unmanaged .dll. In order to do this I'm taking one common approach which is creating a self hosted service and making calls to it.
With that background, I'm having one heck of a time getting the self hosted one working propertly.
here is the code that WORKS:
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/theSvc");
Uri mexUri = new Uri("http://localhost:8080/theSvc/mex");
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(ImgService), baseAddress))
{
// var wsHttpBinding = new WSHttpBinding();
// wsHttpBinding.MaxReceivedMessageSize = int.MaxValue;
// host.AddServiceEndpoint(typeof(IImgService), wsHttpBinding, baseAddress);
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetUrl = mexUri;
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
}
}
Now...if I uncomment these lines in order to increase the maxreceivedMessageSize and remove the baseAddress from the using statement, I can no longer add a reference to the service:
So change this:
using (ServiceHost host = new ServiceHost(typeof(ImgService), baseAddress))
To this:
using (ServiceHost host = new ServiceHost(typeof(ImgService)))
And uncomment this:
// var wsHttpBinding = new WSHttpBinding();
// wsHttpBinding.MaxReceivedMessageSize = int.MaxValue;
// host.AddServiceEndpoint(typeof(IImgService), wsHttpBinding, baseAddress);
The error that I receive is:
... -> local host
There was an error downloading 'http://...:8080/theSvc/_vti_bin/ListData.svc/$metadata'.
The request failed with HTTP status 400: Bad Request.
Metadata contains a reference that cannot be resolved: 'http://...:8080/theSvc'.
Metadata contains a reference that cannot be resolved: 'http://...:8080/theSvc'.
If the service is defined in the current solution, try building the solution and adding the service reference again.
As like everyone else that posts here...I'm in a bind. Any help really appreciated.
It would appear you are not adding the service endpoint.
This is a function I'm using to startup an http host, however I am hosting it in a windows service. Which is the same as your console application. But IIS might think about it a bit differently.
static Uri scannerSvcBaseAddress;
static BasicHttpBinding scannerBinding;
static ServiceHost scannerHost;
public void startScannerWcfService(long eventID)
{
try
{
db.writeServiceLog(eventID, "STARTUP", "=== Scanner WCF Service Starting ===");
string addressToHostAt = ConfigurationManager.AppSettings["ScannerHostBaseAddress"];
if (addressToHostAt != null && addressToHostAt.Trim() != string.Empty)
{
scannerSvcBaseAddress = new Uri(addressToHostAt);
scannerHost = new ServiceHost(typeof(BarCodeService.ScannerService), scannerSvcBaseAddress);
//Allows publishing of METADATA to developers when self hosted on a remote system
ServiceMetadataBehavior smb = scannerHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior();
}
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
scannerHost.Description.Behaviors.Add(smb);
scannerHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
scannerBinding = new BasicHttpBinding();
scannerBinding.MaxReceivedMessageSize = 2147483647;
scannerBinding.Security.Mode = BasicHttpSecurityMode.None;
scannerBinding.OpenTimeout = new TimeSpan(0, 0, 10);
scannerBinding.CloseTimeout = new TimeSpan(0, 0, 10);
scannerBinding.SendTimeout = new TimeSpan(0, 5, 0);
scannerBinding.ReceiveTimeout = new TimeSpan(0, Global.scanUserIdleLogout * 2, 0);
//scannerBinding.ReliableSession.InactivityTimeout = new TimeSpan(2, 0, 0, 0);
scannerHost.AddServiceEndpoint(typeof(BarCodeService.IScannerService), scannerBinding, "");
var behavior = scannerHost.Description.Behaviors.Find<ServiceDebugBehavior>();
behavior.IncludeExceptionDetailInFaults = true;
scannerHost.Open();
db.writeServiceLog(eventID, "STARTUP", "=== Scanner WCF Service Started ===");
}
else
throw new Exception("Host Base Address not provided");
}
catch (Exception ex)
{
db.writeServiceLog(eventID, "STARTUP", string.Format("Error in ServiceManager.startScannerWcfService: {0} {1}", ex.Message, ex.StackTrace));
throw;
}
}
All that said, as was mentioned above if you only need to expose a string WCF may be overkill. I'm using WCF in a windows services to connect to handheld scanners in a warehouse environment, and I am really happy with how it performs. Though it was a huge pain to get it working initially.
But since the question was asked in the context of WCF I thought I would respond with a known to work function that does essentially what you want to do.
I need to develop a WCF Hosted in a console app WebService.
I made it work using the Mutual Certificate (service and client) method using SecurityMode.Message.
But now i need to change the Security Mode to SecurityMode.Transport and use the wsHttpBinding with SSL. I made this code to host the service but i cannot get the wsdl with the browser, or execute some webmethod in the console app client.
static void Main()
{
var httpsUri = new Uri("https://localhost:8089/HelloServer");
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var host = new ServiceHost(typeof(WcfFederationServer.HelloWorld), httpsUri);
host.AddServiceEndpoint(typeof(WcfFederationServer.IHelloWorld), binding, "", httpsUri);
var mex = new ServiceMetadataBehavior();
mex.HttpsGetEnabled = true;
host.Description.Behaviors.Add(mex);
// Open the service.
host.Open();
Console.WriteLine("Listening on {0}...", httpsUri);
Console.ReadLine();
// Close the service.
host.Close();
}
The service is up, but i cannot get nothing on the https://localhost:8089/HelloServer.
On fiddler the get request via browser shows me this message:
fiddler.network.https> HTTPS handshake to localhost failed. System.IO.IOException
What im missing here?
Thanks
EDIT:
The Console Application Client Code
static void Main()
{
try
{
var client = new HelloWorldHttps.HelloWorldClient();
client.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.TrustedPeople,
X509FindType.FindBySubjectName,
"www.client.com");
Console.WriteLine(client.GetData());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
Getting this error:
Could not establish trust relationship for the SSL/TLS secure channel
When it comes to the service, you need to map the certificate to the specific port as described here
http://msdn.microsoft.com/en-us/library/ms733791(v=vs.110).aspx
As for the client, you need to skip the verification of certificate properties like valid date, the domain by relaxing the certificate acceptance policy. An easiest way would be to accept any certiticate
ServicePointManager.ServerCertificateValidationCallback = (a,b,c,d) => true
You can finetune the acceptance callback according to the docs to best fit your needs.
I have a WPF C# application hosting a WCF service. I have a routine to start the service, closing it if it already exists. WebServce is a property of type ServiceHost:
public void Start()
{
try
{
var certificate = new X509Certificate2(certpath, "");
String uri = "net.tcp://" + WCFAddress + "/MyService";
Uri baseaddress = new Uri(uri);
if (WebService != null) {
try {
WebService.Close();
} catch (Exception) {
WebService.Abort();
}
}
WebService = new ServiceHost(MessageProvider, baseaddress);
WebService.Credentials.ServiceCertificate.Certificate = certificate;
WebService.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
WebService.AddServiceEndpoint(typeof(IMessageService), binding, baseaddress);
WebService.Open();
}
catch (Exception e)
{
//exception handling
}
}
This works fine on startup. It also works fine if I change the port number (in WCFAddress) and call the routine again. It also works if I change the address on the host computer and call it with the new IP address. However, if I change the IP address to an invalid one, the service goes into a Faulted state with the error:
e = {"A TCP error (10049: The requested address is not valid in its context) occurred while listening on IP Endpoint=192.168.1.4:5000."}
The Close() call in the above doesn't raise an exception.
If I then change the IP address to the correct one and call again, I get the same error, with the same old incorrect address, even though I passed it the correct one. Also this time the Close() call raises an error due to the Faulted state, which results in the Abort() call.
I thought the Abort() call would allow the service to then be recreated? Why is it giving me an error about the old address when I'm trying to create the service with a new one? It's like it's hanging onto the old ServiceEndpoint?
Abort(). Then just initiate a new instance with the new address.. then Open().