local web service access from remote computer (localhost vs. ip address) - c#

I'm new to using web services.
I created a web service in C# using visual studio 2017 (the service is a .svc file).
This web service is published to a folder on a remote machine.
When I connect to the remote machine, I can run the web service with the url:
http://localhost:1869/ServiceName.svc/
But when I'm trying to run the web service from my computer, I tried to modify the url by replacing 'localhost' with the ip address but it doesn't work.
Is it possible to access remotely a local web service?
If not, what is the best way to publish the web service so that it can be accessed remotely?
Thanks for your help!
-EDIT-
See Web.config code below.
I tried to create a web server on the remote machine and place the Visual Studio solution project / compile it in C:\inetpub\wwwroot, did not help
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="RsConnString" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|RestDB.mdf;User Instance=true" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data></configuration>

Thanks for your help!
I was able to make it work following instruction from there: link
It boils down to configuring IIS and the website correctly.
The key questions to answer were:
Have you enabled basic authentication at the server level in IIS?
Have you enabled remote connections to the Web Management Service?
Have you started the Web Management Service?
Are there management service delegation rules in place?
Does your firewall allow incoming connections to the server on TCP port 8172?

Related

How to access remotely a web service hosted with IIS .NET V4.5

I created a web service using Visual Studio 2017 that is hosted on a remote machine (a remote server) using IIS with .NET V4.5.
The web service publishing to IIS was done using IIS Manager.
I am not able to change the "IP address" to something else than "All Unassigned". If I select the IP address available on the drop down menu, then the web site doesn't work (returning error: "HTTP Error 404. The requested resource is not found.").
If I use "All Unassigned" with "host name" "localhost", it works well locally.
Which means that I can enter the url (http://localhost:81/RestServiceImpl.svc) in a web browser and it execute the web service as expected.
My question is: how can I host my web service on this remote machine so that I can then access it from any computer using the url where localhost would be replaced by the remote machine IP address?
See below my web.config file (it could be that I'm not using the right binding, or that the remote machine IP address is hidden):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="RsConnString" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|RestDB.mdf;User Instance=true" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<handlers>
<remove name="svc-Integrated" />
<add name=".svc" verb="*" path="*.svc" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory,
System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
</handlers>
<!--
<modules runAllManagedModulesForAllRequests="true"/>
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<modules>
<remove name="ServiceModel" />
</modules>
<directoryBrowse enabled="true"/>
</system.webServer>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data></configuration>

Cannot access WCF service using hostname IIS

I've been facing a tough issue for three days. I have a WCF web api (.svc service file) deployed to an IIS 8.5. The application was working properly and then, suddenly, after I changed some other minor things inside the code, this problem arises: I can connect to the application from inside the server (using localhost). I can connect from outside, using the server IP address. But I cannot, by any means, connect from the outside by using server hostname. The problem is best understood through the examples bellow:
Note: the application is an IIS app inside the main Web Site. The service's URI is http://myhostname/api/servicos.svc
http://localhost/api/servico/some_request: works!
http://server_ip_address/api/servico/some_request: works!
http://myhostname.com/api/servico/some_request: DOES NOT WORK!
I have searched through many websites and forums but of no avail.
My web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<customErrors mode="Off" />
</system.web>
<connectionStrings>
<!-- My connection string goes here -->
</connectionStrings>
<system.serviceModel>
<services>
<service name="ServicoWeb.servico" behaviorConfiguration="Wcf_Behavior">
<endpoint name="" binding="webHttpBinding" contract="ServicoWeb.IServico" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp automaticFormatSelectionEnabled="true" defaultBodyStyle="Bare" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Wcf_Behavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="removeSvcDaUrl" type="ServicoWeb.Validacao.UrlCustomizacao, ServicoWeb" />
</modules>
<directoryBrowse enabled="true" />
<rewrite>
<rules>
<remove name="WordPress: https://myhostname.com" />
</rules>
</rewrite>
<handlers accessPolicy="Read, Execute, Script" />
<security>
<requestFiltering>
<verbs>
<add verb="*" allowed="true" />
</verbs>
</requestFiltering>
</security>
</system.webServer>
</configuration>
The error I am presented to when trying to access the API from outside (via hostname) is this:
Server Error in '/Api' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its
dependencies) could have been removed, had its name changed, or is
temporarily unavailable. Please review the following URL and make
sure that it is spelled correctly.
Requested URL: /Api/servico.svc/asos/csv/09655055000104
Version Information: Microsoft .NET Framework Version:4.0.30319;
ASP.NET Version:4.6.1069.1
Do you have any idea what should I do in order to fix this bug?
Edit: one more information: other apps inside the same web site in IIS works FINE! There are even other web apis written in C#, just like this one here, and they all work properly.
Edit 2: another thing important to say is that I can access the service path until the service itself (servico.svc). So, for example, when I try to access "http://myhostname.com/api/servico.svc?wsdl" I successfully get the service's metadata. So, only when I try to access the service itself I get the error mentioned above.
There is a file named host file. When you try request a DN windows look into that file. That file inside C:\WINDOWS\System32\drivers\etc there is host file. Append like below this in your host file (with admin mode).
server_ip_address myhostname.com
I finally got it solved! For those struggling with this issue without sucess: Amazon EC2 load balance was the cause of my troubles.
It happened that Load Balance was set up to filter all requests and send them to the server machines using transport layer SSL security protocol (HTTPS). So, if I were to request http://myserver.com/servico Amazon Load Balance would internally redirect to https://machine-n/servico where 'n' is the machine used (in my case, I have two machines).
So, what caused my issue, inside WCF, was this: my web.config was not allowing the service to accept HTTPS requests. Once I fixed this, everything worked fine.
It also explains why everything worked when I requested directly using the machine's IP address using HTTP: load balance did not play any role in this case filtering the request and redireting using HTTPS.
So, here we have my web.config, now allowing HTTPS requests:
<?xml version="1.0" encoding="UTF-8"?>
...
<system.serviceModel>
<services>
<service name="ServicoWeb.servico" behaviorConfiguration="Wcf_Behavior">
<endpoint name="" binding="webHttpBinding" contract="IServico" bindingConfiguration="webHttpTransportSecurity" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpTransportSecurity">
<security mode="Transport" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp automaticFormatSelectionEnabled="true" defaultBodyStyle="Bare" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Wcf_Behavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
...
In my case below things helped :
Check protocolMapping is binded correctly.
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
Check 443 port is open and working.

WCF not accessible from web

I have imported an a wcf service and it is accessible from local host but when I use my public ip address i am unable to reach it.
This is the contents of my web.config file.
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"
targetFramework="4.0" />
</system.web>
<system.serviceModel>
<extensions>
<bindingExtensions>
<add name="clearUsernameBinding"
type="WebServices20.BindingExtenions.ClearUsernameCollectionElement, ClearUsernameBinding" />
</bindingExtensions>
<!-- Add the inspector attribute as a behavior for displaying SOAP XML packets -->
<behaviorExtensions>
<add name="consoleOutputBehavior"
type="WcfService1.ConsoleOutputBehaviorExtensionElement, WcfService1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<bindings>
<clearUsernameBinding>
<binding name="myClearUsernameBinding"
messageVersion="Soap12" />
</clearUsernameBinding>
</bindings>
<behaviors>
<!-- Add the inspector behavior -->
<endpointBehaviors>
<behavior name="inspectorBehavior">
<consoleOutputBehavior />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="HelloWorldServiceBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="WcfService1.CustomUserNameValidator, WcfService1" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="HelloWorldServiceBehavior"
name="WcfService1.HelloWorldService">
<endpoint address=""
binding="clearUsernameBinding"
bindingConfiguration="myClearUsernameBinding"
contract="WcfService1.IHelloWorldService" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
I have a console app that is able to communicate with it but ONLY with localhost.
This is how I am able to get to it. It is running on port 14946 and have port forwarded that port to the computer that has the service running. It is hosted on IIS.
http://localhost:14946/HelloWorldService.svc?singleWsd
If I use : {publicIP}:14946/HelloWorldService.svc?singleWsd
I get a 500 internal error which means its a configuration issue but I can't seem to pinpoint what the problem is.
EDIT: I am now receiving this error.
The type 'WcfService1.HelloWorldService', provided as the Service attribute value in the ServiceHost directive could not be found. I am able to get to it over the web now but receiving this error now. In order to fix the previous error I had to: 1.) Go to add remove features 2.) Expand MS .NET Framework 3.) Flip on both HTTP and Non-HTTP activation for WCF
Thanks,
If you properly hosted it in IIS you can just remove the port in endpoint and access it directly, something like this: ( add virtual application if necessary )
http://<public ip>/HelloWorldService.svc?singleWsd
It is working in your localhost because it was hosted in IIS Express upon debug mode and automatically assigned that port.

WCF Error - Method Not Allowed

When running the WCF test client and debugging the WCF service locally, everything works fine. After I deploy it to IIS on a remote server and then try loading it with the WCF test client I start getting "Object not set to an instance of object" errors. I added a try-catch to the service and the error changed to "Method not allowed".
I have been reading up on these errors all day and most posts relate to people using JSON or AJAX to access their WCF client. I have tried many of the suggested solutions, most of which were changes to web.config. I am simply accessing it using the test client at this stage, it will be consumed by a Winform application once proven to work.
The 2 methods exposed on the service both create connections to a SQL server on a different domain, although there is a trust set up. I am thinking this could be part of the problem.
My Service Interface
[ServiceContract]
public interface IMeterQueryService
{
[OperationContract]
List<Meter> FindMeter(string mprn);
Implemented Service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MeterQueryService : IMeterQueryService
{
public List<Meter> FindMeter(string mprn)
{
using (var da = new DataAccess())
{
var meters = da.GetMeter(mprn);
da.Dispose();
return meters;
}
}
App Config File
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<connectionStrings>
<add name="Tims" connectionString="hidden" providerName="System.Data.SqlClient"/>
</connectionStrings>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="TimsAPI.MeterQueryService">
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
web config file, site references the WCF service library.
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="false" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="TimsAPI.MeterQueryService">
<endpoint address="http://easvr33:1000/" binding="basicHttpContextBinding" bindingConfiguration=""
contract="TimsAPI.IMeterQueryService" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="localhost" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="false" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Update
I recreated the WCF service as a WCF Service website, rather than a library and it all works now. Something weird between the 2 config files I think. I would still be interested to know why it never worked but I do also understand it may be hard to diagnose for someone without full access to the source
When a WCF service is hosted via an IIS website the service app.config is not used and instead the hosing site's web.config is loaded. All settings needed for the service to work must be duplicated to the web.config of the hosting site.
Might be an issue with serving the SVC to begin with. From here:
1.Open your Virtual Directory’s Properties.
2.Go to the Directory tab.
3.Click Configuration.
4.Click Add…
5.Provide the following information:
a.Executable: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
b.Extension: .svc
c.Verbs: GET,HEAD,POST,DEBUG

WCF Service no Endpoint

When I run WCF Test Client I get an error :
Error: Cannot obtain Metadata from
localhost:52875/ControllersInfo.svc If this is a Windows (R)
Communication Foundation service to which you have access, please
check that you have enabled metadata publishing at the specified
address.
Metadata
contains a reference that cannot be resolved:
localhost:52875/ControllersInfo.svc'. There was no
endpoint listening at localhost:52875/ControllersInfo.svc that
could accept the message. This is often caused by an incorrect
address or SOAP action. See InnerException, if present, for more
details.
Here is my web.config file
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</assemblies>
</compilation>
</system.web>
<system.serviceModel>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
<services>
<service name="dev_FineReceiptsService.ControllersInfo">
<endpoint kind="webHttpEndpoint" contract="dev_FineReceiptsService.IControllersInfo" />
</service>
</services>
</system.serviceModel>
<connectionStrings>
<add name="FineReceiptsTestEntities" connectionString="metadata=res://*/FineTest.csdl|res://*/FineTest.ssdl|res://*/FineTest.msl;provider=System.Data.SqlClient;provider connection string="Data Source=msdev01;Initial Catalog=FineReceiptsTest;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
Can anyone tell me what I have done wrong ?
I tried to find similar question but none of them helped me.
Your service is REST-based service (since you specified the webHttpBinding).
However, the WCF Test Client is a SOAP-based testing tool - you can test SOAP service with this - basicHttpBinding, wsHttpBinding etc.
But you cannot use the SOAP-based WCF Test Client to test your REST-based WCF service... that won't work. Use a regular web browser, potentially combined with Fiddler or something like that to test your REST services .
Metadata endpoints expose WSDL + XSDs which describes SOAP services. There is no support for exposing metadata for REST. Since your are using webHttpEndpoint, you can not use WCFTestClient. For testing a Rest Service, RestSharp or Browser can be used.
If you need to add metadata to SOAP service with simplfied configuration you need to add this behavior:
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

Categories

Resources