Can't call WCF service from WebApplication - c#

I have a simple WCF SOAP service hosted at company's Data Center, having just one Method that receives a Guid (for identifying the request), and returns nothing (void). We use this method as a signal for the service to load its configuration from Database. The service is a self-hosted WCF using SOAP and it is running as a WindowsService.
This service is called from a ASP.NET Web Application, when the user changes configurations related to him. The database is updated, and the service is called to load its updated settings.
The problem is, this service suddenly can't be accessed anymore from the application in production. I get a 404 error, BUT when opening WSDL from browser inside the application's machine, it loads normally.
Trying to reproduce the problem, I created Console Application just to call it from my development machine and it works. BUT, if I try to call it from a new Web Application, another problem happens: "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond".
Also, if I make a call using SoapUI or Visual Studio's WCF Test Client, I can connect without any problem.
For all tests, I used the same approach to made the client: Create a Service Reference (Visual Studio generated code tool). The code used to call the service is something like that:
using (var client = new NotificatorClient())
{
var request = new NotifyRequest { RequestId = Guid.NewGuid() };
client.Notify(request); // Works from any project that is not a WebApplication
Label1.Text = "Notificated!";
}
For all clients, my system.ServiceModel section of Web.config is the same (working on anything that is not a WebApplication, as I said):
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_INotificator">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://myservice.com"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_INotificator"
contract="MyAppNotificatorSvc.INotificator" name="BasicHttpBinding_INotificator" />
</client>
</system.serviceModel>
Also, here's my service contracts, if it helps to understand better any problem that could be happening.
[ServiceContract]
public interface INotificator
{
[OperationContract]
void Notify(NotifyRequest request);
}
[DataContract]
public class NotifyRequest
{
[DataMember(Name = "RequestId", Order = 0, IsRequired = true)]
public Guid RequestId { get; set; }
}
We are using HTTPS with TLS 1.2 as our security protocol over requests, and Itried to change it by calling this code on the WebApplication, but I still have the same problem.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
I know that this may sound like not really relevant information about the problem, but this is as far as I got until now. Does anyone came into this type of problem? Any tip on what could be happening?

Related

Adding ASMX service to IIS for use with Biztalk

I've created a local webservice (.asmx), that I want to add to IIS. The service needs to be called from a Send Adapter in Biztalk.
My project in Visual Studio is structured like so:
There's a single .asmx file, that contains a single web method, see code below:
public class LocalWebService : System.Web.Services.WebService
{
private BankConnectClient client;
[WebMethod]
public void TransferPayment()
{
ProcessDirectory("C:\\Test\\BankConnectTestFiles");
}
I'm not very familiar with IIS, so I don't know best approch to add this service to run on my localhost. I tried adding a new website and placed the project folder in C:\inetpub\wwwroot, which I then reference in IIS with the following settings:
But when I browse to the root http://localhost:61406/, I receive an HTTP Error 403.14.
What is the correct approach in deploying an asmx web service to IIS, to then call in Biztalk using either the WCF-Custom or WCF-BasicHttp adapter?
It seems that the problem has been solved. The service URL need the LocalWebService.asmx suffix.
Besides, as far as I know, BasicHttpBinding in the WCF aims to compatible with ASMX web service, why not try to create a WCF service with BasicHttpBinding. And this is also supported by the BizTalk.
I Have made a demo, wish it is useful to you.
VS template.
Add the following code snippets to the default webconfig.
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<!--add the following line to support http protocol-->
<add binding="basicHttpBinding" scheme="http"/>
</protocolMapping>
Then publish the project to the IIS folder and add the http binding to the IIS site binding module. We might need to enable the WCF support.
Result.
Feel free to let me know if there is anything I can help with.

Call Soap Service From a Windows Service

I am consuming a Soap service http://example.com/soap/webservice.php in my desktop application . i created a separate class library Included the service and used this class library to consume it in my main application which i working fine.
Here is the code i am using:
MyService.PushServerWSPortTypeClient obj = new MyService.PushServerWSPortTypeClient();
string result = obj.auth(apiId, UserName, Password);
This is working perfect.
But when i use this service in my windows service i am getting the exception:
There was no endpoint listening at http://exmaple.com/soap/webservice.php that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
I know what this exception means that it is unable to find endpoint of it in my service, but in my class library endpoints are mentioned in it's app.config and i also added these endpoints in my windows service app.config as well.
Here is the code from app.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="PushServerWSBinding" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://example.com/soap/webservice.php"
binding="basicHttpBinding" bindingConfiguration="PushServerWSBinding"
contract="MyService.PushServerWSPortType" name="PushServerWSPort" />
</client>
</system.serviceModel>
Inner Exception Message :
The remote name could not be resolved: 'api.example.com'
Stack Trace :
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.GetOutputStream()
It is possible that your browser uses some proxy where your code does not (or use different one).
If it is the case make sure to set WebClient.Proxy property to match one in the browser, making use of the WebProxy class using
WebClient webClient = new WebClient())
{
webClient.Proxy = new WebProxy("myproxy.com");
result= webClient.DownloadString(someURL);
}
If not sure, try out his DNS-Testing link. It is unlikely, but possible if browser uses different DNS than your code.
After digging one complete day,Today we contacted our Networks Department for this weird issue and we came to know that When we use Desktop Application to call any SOAP or WCF Service the request goes through Proxy Server, but in the case of Windows Service the request goes through System Gateway/Firewall and on Firewall port 80 was blocked, due to which the request was unable to call server.
When we opened the port 80 for the service specific url it started wroking normally.

Could not establish secure channel for SSL/TLS with authority 'xxxxx.com'

I'm trying to write a client against a customer's SOAP webservice, using VS2013 and WCF. The webservice itself is behind their firewall, so they've established a proxy that I'm trying to contact. (The proxy seems to be implemented using MuleSoft's ESB, which may or may not be relevant.)
I've been given an https: url, and a username/password. When I load the url into a browser, I'm prompted for the username/password, and then I see the .wsdl. The .wsdl specifies an internal url that I can't access, but I figure that's for the actual site.
When I create a Service Reference in VS2013, using the proxy URL, I'm prompted for the username/password three times, then I get a proper client, settings in app.config, etc.
The generated bindings in the app.config are for a basicHttpBinding with security mode Transport, and an endpoint address pointing to that inaccessible internal url.
So, from the generated bindings, I:
Replace the inaccessible internal url with the proxy url I've been given.
Change the security mode to "TransportWithMessageCredentials"
<bindings>
<basicHttpBinding>
<binding name="MyCustomersServiceSoapBinding">
<security mode="TransportWithMessageCredential" >
<message clientCredentialType="UserName" />
</security>
</binding>
<binding name="MyCustomersServiceSoapBinding1" />
</basicHttpBinding>
</bindings>
Replace the ClientCredentials with username and password:
using (var client = new MyCustomersServiceClient())
{
var loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = "ausername";
loginCredentials.UserName.Password = "apassword";
var defaultCredentials = client.Endpoint.Behaviors.Find<ClientCredentials>();
client.Endpoint.Behaviors.Remove(defaultCredentials);
client.Endpoint.Behaviors.Add(loginCredentials);
var myData = new MyData
{
};
var result = client.receiveData(myData);
}
When I run it, I get an exception:
Could not establish secure channel for SSL/TLS with authority 'xxxxx.com'.
Browsing around, most of what I find suggests problems with ssl certificates, but I'm not sure that makes sense. If that were the case, I'd expect to see issues when I view the .wsdl through the browser. And I thought that by removing the default client credentials, I'd be bypassing the certificate check. And I am seeing a few posts about more obscure problems that result in this same error message.
I've turned on SOAP message logging, but that's provided me with no information. It shows the failed outgoing message, but nothing of use.
So I've been looking at the traffic in Fiddler. I see two messages, an HTTP message to "Tunnel to" with Result 200, and an HTTPS message to the proxy url with Result 401.
At this point, I see two possibilities:
I need to install an SSL certificate, the way the error message would suggest, or
the problem is simply that I'm not providing the username/password to the service in a way that it understands, and it's rejecting my attempt to connect.
I'm leaning towards the latter. My problem? I know nothing about the system that's hosting the service. I'm passing username/password in what I thought was the usual mechanism for WCF, and it's not working.
So, finally, the questions:
Have I misled myself, and I do need to be messing about with SSL certificates?
If not, what do I do in WCF to pass a username/password to an HTTPS webservice, hosted by MuleSoft
ESB? (Mule EE Core Extensions/3.5.1, if that helps).
Not sure if the issue I encountered shares the same cause as your issue, but just in case I can help someone with this, adding requireClientCertificate=true solved my problem:
<bindings>
<customBinding>
<binding name="bindingName">
...
<httpsTransport requireClientCertificate="true"/>
</binding>
</customBinding>
</bindings>
I had the same error message, but the web service I'm consuming is over HTTPS and requires a SSL certificate as authentication.
Many endpoints have been disabling TLSV1.0 and TLSV1.1 recently
try:
CURL https://<<service host>> -v -TLSV1.0
and
CURL https://<<service host>> -v -TLSV1.2
For instance, https://www.comodo.com doesn't allow TLSV1.0 or TLSV1.1 but does allow TLSV1.2.

Call Sharepoint Web Service over SSL with Silverlight

I have a Silverlight 5 app that gets some data from a couple Sharepoint lists. It was all working correctly, then we set up the site to allow SSL and I tried to update the service reference to call the webservice using https. It updated the client config binding to use security mode Transport. But when it calls the service it's giving an error:
System.ServiceModel.CommunicationException: An error occurred while trying to make a request to URI 'https://devlpadmin.thelittlegym.com/_vti_bin/Lists.asmx'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details. ---> System.Security.SecurityException ---> System.Security.SecurityException: Security error.
Does anyone know what the problem is or how to get more info than "Security error."?
I've gone through so many different combinations of things that I'm not sure exactly what has happened when, but it's now working. I think originally the site/service was having some weird problem that prompted me to try to manually configure Silverlight to pass NTLM transport credentials. In doing so, I might have created an invalid config file causing the error. The configuration that is working is:
<bindings>
<basicHttpBinding>
<binding name="ListsSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://devadmin.mydomain.com/_vti_bin/Lists.asmx"
binding="basicHttpBinding" bindingConfiguration="ListsSoap"
contract="SPListsService.ListsSoap" name="ListsSoap" />
</client>
So if you're having this error and not making a cross-domain call, suspect some kind underlying service error. If you're not using Silverlight, you can enable tracing to track down the error. If you are using Silverlight, I still don't know what can be done to narrow it down, but be aware that Silverlight only supports a fragment of the configuration options that a normal .net WCF client does.

I need to develop a WCF service that will only be exposed thru HTTP/HTTPS. How to use HTTP cookies?

First of all, I admit I'm a newbie in WCF. Still not out of the training wheels.
I was assigned to develop a WCF service, and part of the requirements is that a sort of "session token" needs to be passed with each request as an HTTP cookie. (Predictably, such token needs be generated in the HTTP response headers of a successful "logon" call in such service).
Is this straightforward?
Disclaimer: you're not really supposed to do any of this, because it's forcing a WCF service to behave as a web service. But if you need cookies, read on.
If all you need is the session id, you can get it from:
OperationContext.Current.SessionId
If you need cookies, you'll need to jump through some hoops. The gist of it is (1) set asp.net compatibility, and (2) reference HttpContext.Current properties.
Your service will need to use a wsHttpBinding (or another binding that supports sessions). If create your project to be a WCF service hosted in IIS, you'll get these by default. You'll also need to set asp.net compatibility in the config file.
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="MyBinding" allowCookies="false" ... </binding>
</wsHttpBinding>
</bindings>
(see the link here for why I have allowCookies=false)
To enable sessions, on your WCF Service Contract, set the following
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IMyWcfService {...}
You may also want to set the ServiceBehavior on the service itself (PerSession is the default), and you'll need to set asp.net compatibility.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
public class MyWcfService : IMyWcfService {...}
Some relevant properties you then have access to:
// Gives you the current session id as a string
HttpContext.Current.Session.SessionID
// Indicates whether the service is using sessionless cookies
HttpContext.Current.Session.CookieMode
// Indicates whether the session id is stored in the url or in an HTTP cookie
HttpContext.Current.Session.IsCookieless
// The cookies themselves
HttpContext.Current.Request.Cookies
HttpContext.Current.Response.Cookies
// The session and cache objects
HttpContext.Current.Cache
HttpContext.Current.Session
A link on sessions in WCF Services:
http://msdn.microsoft.com/en-us/library/ms733040.aspx
HTH,
James
This topic on msdn could help you out http://msdn.microsoft.com/en-us/library/bb398778.aspx.
Also, this could help you out with hosting you`r WCF service inside IIS: http://msdn.microsoft.com/en-us/library/aa702682.aspx
and http://msdn.microsoft.com/en-us/library/bb332338.aspx (Hosting Using Internet Information Services)
This just answers your question partially, but will give you a head start with config.
In your config file under the service config section, create basic http bindings like that:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="myHttpBinding" allowCookies="true">
</binding>
</basicHttpBinding>
</system.serviceModel>
Then read up on wcf binding and endpoints configuration.

Categories