I am trying to make my Windows Service, which hosts a WCF service cross-domain compatible.
After hours and hours of searching I was told that I needed to create another service which will load the crossdomain.xml and clientaccesspolicy.xml files so that the Windows hosted WCF service can be run on any domain.
This is my main service :
Namespace UmbrellaMobileService
<RunInstaller(True)> _
Public Class ProjectInstaller
Inherits Installer
Private process As ServiceProcessInstaller
Private service As ServiceInstaller
Private components As System.ComponentModel.Container
Public Sub New()
process = New ServiceProcessInstaller()
process.Account = ServiceAccount.LocalSystem
service = New ServiceInstaller()
service.ServiceName = "UmbrellaMobileService"
service.DisplayName = "Umbrella Mobile Service"
service.Description = "Handels Umbrella Mobile Requests."
Installers.Add(process)
Installers.Add(service)
End Sub
End Class
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class UmbrellaMobileService
Inherits ServiceBase
Public serviceHost As ServiceHost = Nothing
Public CrossDomainServiceHost As ServiceHost = Nothing
Public Shared Sub Main()
ServiceBase.Run(New UmbrellaMobileService())
End Sub
Public Sub New()
ServiceName = "UmbrellaMobileService"
End Sub
'Start the Windows service.
Protected Overloads Overrides Sub OnStart(ByVal args As String())
If serviceHost IsNot Nothing Then
serviceHost.Close()
End If
serviceHost = New WebServiceHost(GetType(UmbrellaService), New Uri("http://localhost/UmbrellaMobileService"))
serviceHost.AddServiceEndpoint(GetType(IUmbrellaMobileService), New WebHttpBinding(), "http://localhost/UmbrellaMobileService")
CrossDomainServiceHost = New ServiceHost(GetType(CrossDomainService))
Else
System.Diagnostics.EventLog.WriteEntry("Umbrella Mobile Service", objIniFile.ErrorMessage, EventLogEntryType.Error)
serviceHost.Close()
CrossDomainServiceHost.Close()
End If
serviceHost.Open()
CrossDomainServiceHost.Open()
End Sub
' Stop the Windows service.
Protected Overloads Overrides Sub OnStop()
If serviceHost IsNot Nothing Then
serviceHost.Close()
CrossDomainServiceHost.Close()
serviceHost = Nothing
End If
End Sub
End Class
<AspNetCompatibilityRequirements(Requirementsmode:=AspNetCompatibilityRequirementsMode.Allowed)> _
Public Class UmbrellaService
Inherits System.Web.Services.WebService
Implements IUmbrellaMobileService
Function GetCustomers() As Stream Implements IUmbrellaMobileService.GetCustomers
'Function Logic
End Function
End Class
End Namespace
This is my Implementation of my main service:
Namespace UmbrellaMobileService
<ServiceContract()> _
Public Interface IUmbrellaMobileService
<OperationContract()> _
<WebInvoke(Method:="GET", BodyStyle:=WebMessageBodyStyle.Bare, ResponseFormat:=WebMessageFormat.Json, RequestFormat:=WebMessageFormat.Json)> _
Function GetCustomers() As Stream
End Interface
End Namespace
This is the 'Cross Domain Service' I was advised to add:
Namespace UmbrellaMobileService
Public Class CrossDomainService
Implements ICrossDomainService
Public Function ProvidePolicyFile() As System.ServiceModel.Channels.Message Implements ICrossDomainService.ProvidePolicyFile
Dim filestream As FileStream = File.Open("ClientAccessPolicy.xml", FileMode.Open)
' Either specify ClientAccessPolicy.xml file path properly
' or put that in \Bin folder of the console application
Dim reader As XmlReader = XmlReader.Create(filestream)
Dim result As System.ServiceModel.Channels.Message = Message.CreateMessage(MessageVersion.None, "", reader)
Return result
End Function
End Class
End Namespace
And here is its Implementation :
Namespace UmbrellaMobileService
<ServiceContract()> _
Public Interface ICrossDomainService
<OperationContract(), WebGet(UriTemplate:="ClientAccessPolicy.xml")> _
Function ProvidePolicyFile() As Message
End Interface
End Namespace
My config file looks like this :
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="CrossDomainServiceBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="UmbrellaMobileService.UmbrellaMobileService">
<endpoint address="" binding="basicHttpBinding" contract="UmbrellaMobileService.IUmbrellaMobileService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/UmbrellaMobileService"/>
</baseAddresses>
</host>
</service>
<service name="UmbrellaMobileService.CrossDomainService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="UmbrellaMobileService.ICrossDomainService" behaviorConfiguration="CrossDomainServiceBehavior"/>
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/></system.web></configuration>
Now, I get this error when I attempt to run this service:
Service cannot be started. System.InvalidOperationException: Service has zero application (non-infrastructure) endpoints.
This might be because no configuration file was found for your application,
or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
I have searched and searched and still do not know what to do, can anyone give me some advice?
I had the same issue and here is how I fixed it.
First, create a new service class that will serve up the clientaccesspolicy.xml when a client requests it:
[ServiceContract]
public class CrossDomainPolicyService
{
private Stream StringToStream(string result)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
public Stream GetClientAccessPolicy()
{
string result = #"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"">
<domain uri=""*""/>
</allow-from>
<grant-to>
<resource path=""/"" include-subpaths=""true""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>";
return StringToStream(result);
}
}
Next, modify your app.config file to expose the new service:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="policyBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="MyNamespace.MyService">
<endpoint address="" binding="basicHttpBinding" contract="MyNamespace.IMyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9876/MyService/" />
</baseAddresses>
</host>
</service>
<service name="MyNamespace.CrossDomainPolicyService">
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.CrossDomainPolicyService" behaviorConfiguration="policyBehavior">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<!-- Root Domain where the other service is hosted -->
<add baseAddress="http://localhost:9876/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
... and that should do it!
Related
My App.config file is
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1">
<endpoint address="http://localhost:8733/service1"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
My service1.cs code is as below
using System;
using System.ServiceModel.Web;
namespace WcfJsonRestService
{
public class Service1 : IService1
{
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "data/{id}")]
public Person GetData(string id)
{
// lookup person with the requested id
return new Person()
{
Id = Convert.ToInt32(id),
Name = "Leo Messi"
};
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}
Initially this was giving issue as
WCF Service Host Configuration - Please try changing the HTTP port to 8733
So I had followed Executing the following code in CMD
netsh http add urlacl url=http://+:8733/ user=WORK\Clara
After executing this code I am facing new error as below
How can I resolve this issue?
I have also tried updating the App.Config as said over below link but then after I was getting some another error
WCF service host cannot find any service metadata
You are missing service metadata behavior configuration. Please add below configuration:
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733"/>
</baseAddresses>
</host>
<endpoint address="service1"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled ="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
I am working on ASP.NET WCF simple HelloWorld Example. I have successfully completed server side but I am getting issue while working on client side. I have used SVCUTIL.exe to generate proxy classes for me.
On debug I am getting following error;
An exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll but was not handled in user code
Additional information: Could not find endpoint element with name 'WSHttpBinding_IHelloWorldService' and contract 'IHelloWorldService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element.
another thing, can I use Channel Factory if I don't access to dll file from server, say If I got access to WSDL url link
On Client Side app.config
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IHelloWorldService" />
<binding name="WSHttpBinding_IHelloWorldServiceAsyn" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8087/CreditUnionServices/HelloWorldServices/HelloWorldService"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHelloWorldService"
contract="IHelloWorldService" name="WSHttpBinding_IHelloWorldService">
<identity>
<userPrincipalName value="DESKTOP-G6LE8I4\Khurram Zahid" />
</identity>
</endpoint>
<endpoint address="http://localhost:8087/CreditUnionServices/HelloWorldServices/HelloWorldServiceAsyn"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHelloWorldServiceAsyn"
contract="IHelloWorldServiceAsyn" name="WSHttpBinding_IHelloWorldServiceAsyn">
<identity>
<userPrincipalName value="xyz\abc" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Client Proxy Channel Factory
public class HelloWorldClient
{
public string SendTestMessage(string name)
{
ChannelFactory<IHelloWorldService> _HelloWorldClientService = new ChannelFactory<IHelloWorldService>("WSHttpBinding_IHelloWorldService");
IHelloWorldService _HelloWorldChannelService = _HelloWorldClientService.CreateChannel();
var _returnMessage = _HelloWorldChannelService.GetMessage(name);
((IClientChannel)_HelloWorldChannelService).Close();
return _returnMessage;
}
}
Server side config file
<system.serviceModel>
<services>
<service name="App.Services.Managers.HelloWorldManager" behaviorConfiguration="DefaultServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8087/CreditUnionServices/HelloWorldServices"/>
</baseAddresses>
</host>
<endpoint address="HelloWorldService" binding="wsHttpBinding" contract="App.Services.Contracts.IHelloWorldService"></endpoint>
<endpoint address="HelloWorldServiceAsyn" binding="wsHttpBinding" contract="App.Services.Contracts.IHelloWorldServiceAsyn"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultServiceBehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
Update Code
public static class HelloWorldClient
{
public static string SendTestMessage(string name)
{
HelloWorldServiceClient _helloWorldService = new HelloWorldServiceClient("WSHttpBinding_IHelloWorldService");
var _returnMessage = _helloWorldService.GetMessage("mr kz ....");
return _returnMessage;
}
}
Um quite new to WCF . I think I have messed up a bit. So this is what I did so far and I ve hosted my WCF service in IIS
First the Contracts
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using YangkeeServer.dto;
namespace YangkeeServer
{
public class Service1 : IService1
{
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "single")]
public YangkeeTrailerDTO getTrailor()
{
return new YangkeeTrailerDTO()
{
loanFrom = "heaven"
};
}
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "datum/{id}")]
public Test getName(string id)
{
return new Test()
{
Id = Convert.ToInt32(id) * 12,
Name = "Leo Messi"
};
}
}
}
and this is my web.config file
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="YangkeeServer.Service1">
<endpoint
contract="YangkeeServer.IService1"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/Service1.svc">
</endpoint>
</service>
<service name="YangkeeServer.Service2">
<endpoint
contract="YangkeeServer.IService2"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/Service2.svc">
</endpoint>
</service>
<service name="YangkeeServer.YangkeeTrailer">
<endpoint
contract="YangkeeServer.IYangkeeTrailor"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/YangkeeTrailor.svc">
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebHttp">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
and um using this urlhttp://localhost:7000/Service1.svc and um getting this error
Server Error in '/' Application.
When 'system.serviceModel/serviceHostingEnvironment/multipleSiteBindingsEnabled' is set to true in configuration, the endpoints are required to specify a relative address. If you are specifying a relative listen URI on the endpoint, then the address can be absolute. To fix this problem, specify a relative uri for endpoint 'http://localhost:7000/Service1.svc'.
can any one tell me where did I do wrong? Thank you in advance.
Set the service endpoint address to just the service filename (this is the relative part):
address="Service1.svc"
or set the address to blank for each endpoint (I don't think its needed when hosting in the development environment or in IIS)
address=""
See this answer to another question
The relevant part is:
the virtual directory (in IIS) where your *.svc file exists defines your service endpoint's address.
To fix this error, I added... listenUri="/" ... to the service endpoint.
Example:
<service name="_name_">
<endpoint address="http://localhost:_port_/.../_servicename_.svc"
name="_servicename_Endpoint"
binding="basicHttpBinding"
bindingConfiguration="GenericServiceBinding"
contract="_contractpath_._contractname_"
listenUri="/" />
</service>
MSDN: Multiple Endpoints at a Single ListenUri
This works for me:
1. Insert this lines inside service:
<host>
<baseAddresses>
<add baseAddress="http://localhost:7000/Service1.svc" />
</baseAddresses>
</host>
2. Set the value of address as bellow:
address=""
The full code:
<service name="YangkeeServer.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:7000/Service1.svc" />
</baseAddresses>
</host>
<endpoint
contract="YangkeeServer.IService1"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="">
</endpoint>
</service>
I'm getting the notorious, "The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error" in my project. It's a WCF PollingDuplex Service, consumed by a Silverlight 4 project.
I'm requesting a document with the service, so I can display it in a viewer in my SL application.
Here is the Server Web Config XML:
<system.serviceModel>
<extensions>
<bindingExtensions>
<add name="pollingDuplex" type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement,System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
</extensions>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior name="PortalOnlineBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<pollingDuplex>
<binding name="SLPollingDuplex" duplexMode="MultipleMessagesPerPoll" />
</pollingDuplex>
</bindings>
<services>
<service name="Online.Web.PortalOnline" behaviorConfiguration="PortalOnlineBehavior">
<endpoint address="" binding="pollingDuplex" bindingConfiguration="SLPollingDuplex"
contract="Notification.IPortalOnline" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://portalonline.com/PortalOnline/IPortalOnline" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Here is the Object I'm trying to return to SL via this WCF service
Imports System.ServiceModel
Imports System.Runtime.Serialization
Imports DocCave.Common
Imports System.Xml
Imports System.IO
<DataContract(NAMESPACE:=DataStore.NAMESPACE)>
Public Class PortalDocument
<DataMember()>
Public Property DataSource As Byte()
<DataMember()>
Public Property FileName As String
<DataMember()>
Public Property FileType As String
End Class
Here's the WCF Method that is being called:
Public Function GetDocument(sessionUserMeta As Common.UserMetaData, docId As System.Guid) As Notification.PortalDocument Implements Notification.IPortalOnline.GetDocument
Dim doc As Documents.Document = Documents.Document.GetDocument(docId, sessionUserMeta)
Dim portalDoc As New PortalDocument
portalDoc.DataSource = doc.DataSource
portalDoc.FileName = doc.QueryPackage.DocumentName
portalDoc.FileType = doc.QueryPackage.Type
Return portalDoc
End Function
Further Details:
This works perfectly for one or two document request, and the gives me the above mentioned error. For instance, I can load a default document when the SL application is loaded using this method with this service, and it populates perfectly. I can then go to a tree view I have, and select a document, and it works perfect for the first document... but after that, error. Also, I've noticed sometimes it will only work once, if I select certain pdfs that are a bit larger (250kb or so..) ... oh, and I forgot... here's the code in my SL application that is connecting to the WCF service. I'm using the "GetBaseWebAddress()" because I'm using dynamic sub domains, so part of the address can be different each time...
Private Sub LoadClient()
Dim bind As New PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll)
Dim endpoint As New EndpointAddress(GetBaseWebAddress() & "PortalOnline/PortalOnline.svc")
Me.client = New PortalOnline.PortalOnlineClient(bind, endpoint)
AddHandlers()
End Sub
I've struggled with this for a while, so any help would be greatly appreciated...
We've tried to use a very very simple WCF service with a HTTp Get and we can't get it work.
We've followed those "guide" but it doesn't work
http://msdn.microsoft.com/en-us/library/bb412178.aspx
http://www.dotnetfunda.com/articles/article779-simple-5-steps-to-expose-wcf-services-using-rest-style-.aspx
When we call our service with the following url, we get a page not found error:
http://localhost:9999/Service1.svc/GetData/ABC
The base url (http://localhost:9999/Service1.svc) works fine and returns the wcf service information page correctly.
Those are the steps and code to reproduce our example.
In Visual Studio 2010, create a new "WCF Service Application" Project
Replace the IService interface with this code
[ServiceContract()]
public interface IService1
{
[OperationContract()]
[WebInvoke(Method = "GET",
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "GetData/{value}")]
string GetData(string value);
}
Replace the Service class with this code
public class Service1 : IService1
{
public string GetData(string value)
{
return string.Format("You entered: {0}", value);
}
}
The web.config look like this
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="Service1">
<endpoint address="" binding="webHttpBinding" contract="IService1" behaviorConfiguration="WebBehavior1">
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebBehavior1">
<webHttp helpEnabled="True"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
Press Run and try to call the Get method
If someone get this or something similar working, it would be very kind if you could reply information about the working example.
Thank you very much
I recreated your sample - works like a charm.
One point: do your service contract (public interface IService1) and service implementation (public class Service1 : IService1) exist inside a .NET namespace??
If so, you need to change your *.svc and your web.config to include:
<services>
<service name="Namespace.Service1">
<endpoint address="" binding="webHttpBinding"
contract="Namespace.IService1"
behaviorConfiguration="WebBehavior1">
</endpoint>
</service>
</services>
The <service name="..."> attribute and the <endpoint contract="..."> must include the .NET namespace for this to work.