Reputation: 23
I have a problem when I try to access the WCF service hosted in a Windows service directly from a web application and I can't understand what I am doing wrong.
I try all suggestion which I found and didn't help anything. I use AngularJs, but that is not important, I accept all suggestions.
There is my project: https://github.com/djromix/Portal.WorckFlow
Portal.Services
is the Windows service.
This is my windows service configuration:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Portal.Services.ServiceContract.PortalContract">
<endpoint
address=""
binding="basicHttpBinding"
contract="Portal.Services.ServiceContract.IPortalContract">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/Portal" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Service Code:
namespace Portal.Services.ServiceContract
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IPortalContract" in both code and config file together.
[ServiceContract(Namespace = "")]
public interface IPortalContract
{
[WebInvoke(ResponseFormat = WebMessageFormat.Json, Method = "GET", BodyStyle = WebMessageBodyStyle.Wrapped)]
double Ping();
[OperationContract]
object CashInResult(string key);
}
}
namespace Portal.Services.ServiceContract
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class PortalContract : IPortalContract
{
public double Ping()
{
return -1;
}
[WebGet]
[WebInvoke(ResponseFormat = WebMessageFormat.Json, Method = "GET", BodyStyle = WebMessageBodyStyle.Wrapped)]
public object CashInResult(string key)
{
return new {Value = "Some Data"};
}
}
}
I just want simple access the url and get the json result
http://localhost:8000/Portal/CashInResult?key=secretkey
Now i get the error [Failed to load resource: the server responded with a status of 400 (Bad Request)]
From web application i get the error
XMLHttpRequest cannot load /Portal/CashInResult?key=1. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '???' is therefore not allowed access. The response had HTTP status code 400.
Upvotes: 2
Views: 1565
Reputation: 23
After many tries i found the solution.
namespace Portal.Services.ServiceContract
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IPortalContract" in both code and config file together.
[ServiceContract(Namespace = "")]
public interface IPortalContract
{
[WebInvoke(ResponseFormat = WebMessageFormat.Json, Method = "GET", BodyStyle = WebMessageBodyStyle.Wrapped)]
double Ping();
[OperationContract]
string CashInResult(string key);
}
}
namespace Portal.Services.ServiceContract
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class PortalContract : IPortalContract
{
readonly Logger _nLog = LogManager.GetCurrentClassLogger();
public double Ping()
{
using (var tMeter = new TimeMeterLog(_nLog, "Ping"))
{
tMeter.Info("-1");
return -1;
}
}
[WebGet(UriTemplate = "/CashInResult/{key}", ResponseFormat = WebMessageFormat.Json)]
public string CashInResult(string key)
{
using (var tMeter = new TimeMeterLog(_nLog, "CashInResult"))
{
var result = JsonConvert.SerializeObject(new { Value = "Some Data" });
tMeter.Info(result);
return result;
}
}
}
}
Call service from browser:
http://localhost:8000/rest/Ping
Result:{"PingResult":-1}
There is source code. https://github.com/djromix/Portal.WorckFlow
Upvotes: 0
Reputation:
To get your GET request to work you could add the header (Access-Control-Allow-Origin) to the request yourself in the browser but only GET requests will work.
If you are running WCF in a windows service then system.webServer is not being used as there is no IIS.
This link show how to achieve fully CORS in WCF outside of IIS..
https://code.msdn.microsoft.com/windowsdesktop/Implementing-CORS-support-c1f9cd4b
but its a bit long to explain in an SO post but this is why its not working for you at the moment....
There are two types of requests in the CORS world, “normal” requests and "preflight" requests.
A normal, or safe (HTTP GET) request involves the browser sending an ORIGIN header with the request, and the server accepting/rejecting based on that.
A preflight, or unsafe (such as POST, PUT or DELETE) request involves the browser sending an HTTP OPTIONS request asking for permission to send the actual request to the server.
IIS looks after all this for you when you enable the settings in the system.webServer section. Hosting WCF as a windows service takes IIS out the picture, so in WCF you need to implement the CORS stuff yourself.
I think you should reconsider though and use IIS if the service's purpose is to serve HTTP requests.
Upvotes: 1