CrossDomainError on IIS7 Silverlight 3 WCF app - wcf

* Readers Beware: massive code dump, not for the faint of heart... *
Hello,
I'm trying to figure out how to deploy a Silverlight 3 app to IIS7 with a WCF Service. I think i've got most of it figured out however I still get a cross domain error for some reason. I'm leaning toward thinking that the service is not finding the client access policy but I'm not sure how to confirm this. I get a very useless exception (simply says CrossDomainError). Inner Exception is nonexistant. Here are the steps I've taken to deploy the app. If anyone sees anything that doesn't add up can they please advise? I can't think of anything else to poke at right now...
In IIS manager I built a new site. I named it Silverlight, accepted a pool of the same name, and accepted all the rest of the defaults. I disabled the default site. I set the web root to be C:\WebApps
I placed all of the files from the release build of my Visual Studio Silverlight client project into the web root.
I place the following config files from the Silverlight client project in the web root: ServiceReferences.ClientConfig, Silverlight.js.
I placed the /bin directory from the release build of the Silverlight.Web project into the web root
I place the following files from the Silverlight.Web release build in the web root: crossdomain.xml, clientaccesspolicy.xml, Service1.svc, Service1.svc.cs, Web.config.
I renamed the TestPage.html file to index.html.
I realize that many of these are superfluous but I was running out of things to try so I started adding anything that looked like it might contain any useful metadata.
Here is the code to my various config files:
clientaccesspolicy.xml:
<?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 include-subpaths="true" path="/"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
crossdomain.xml:
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>
system.serviceModel configuration, excerpted from Web.config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SilverlightApplication2.Web.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="customBinding0">
<binaryMessageEncoding/>
<httpTransport/>
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service behaviorConfiguration="SilverlightApplication2.Web.Service1Behavior" name="SilverlightApplication2.Web.Service1">
<endpoint address="http://win-xqawq222tag:2721/Service1.svc" binding="customBinding" bindingConfiguration="customBinding0" contract="SilverlightApplication2.Web.Service1"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
ServiceReferences.ClientConfig:
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_Service1">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://win-xqawq222tag:2721/Service1.svc" binding="customBinding"
bindingConfiguration="CustomBinding_Service1" contract="ServiceReference1.Service1"
name="CustomBinding_Service1" />
</client>
</system.serviceModel>
</configuration>
Service1.svc:
<%# ServiceHost Language="C#" Debug="true" Service="SilverlightApplication2.Web.Service1" CodeBehind="Service1.svc.cs" %>
Now for the implementation followed by the client code:
Service1.svc.cs:
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;
namespace SilverlightApplication2.Web
{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1
{
[OperationContract]
public DoWorkResult DoWork()
{
// Add your operation implementation here
int i = new Random().Next();
string s = "test string";
DoWorkResult r = new DoWorkResult() { String = s, Integer = i };
return r;
}
// Add more operations here and mark them with [OperationContract]
}
[DataContract]
public class DoWorkResult
{
[DataMember]
public string String { get; set; }
[DataMember]
public int Integer { get; set; }
}
}
MainPage.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SilverlightApplication2
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
ServiceReference1.Service1Client proxy = new SilverlightApplication2.ServiceReference1.Service1Client();
proxy.DoWorkCompleted += new EventHandler<SilverlightApplication2.ServiceReference1.DoWorkCompletedEventArgs>(proxy_DoWorkCompleted);
proxy.OpenAsync();
proxy.DoWorkAsync();
proxy.CloseAsync();
}
void proxy_DoWorkCompleted(object sender, SilverlightApplication2.ServiceReference1.DoWorkCompletedEventArgs e)
{
if (e.Error == null)
{
String.Text = "Test String is: " + e.Result.String;
Integer.Text = "Random Int is: " + e.Result.Integer;
}
else
{
String.Text = e.Error.Message + e.Error.InnerException.Message + e.Error.StackTrace;
Integer.Text = e.Error.Message + e.Error.InnerException.Message + e.Error.StackTrace;
}
}
}
}
All of this works fine in VS 2008 on XP Pro. On IIS7 on Server2008 I am able to hit the default page, index.html, at http://localhost or at http://[myComputerName].
I am also able to hit the service at http://localhost/Service1.svc. I am not able to hit the service using http://[compNameHere]/Service1.svc. It complains with this error:
No protocol binding matches the given
address
'http://win-xqawq222tag:2721/Service1.svc'.
Protocol bindings are configured at
the Site level in IIS or WAS
configuration. Description: An
unhandled exception occurred during
the execution of the current web
request. Please review the stack trace
for more information about the error
and where it originated in the code.
Exception Details:
System.InvalidOperationException: No
protocol binding matches the given
address
'http://win-xqawq222tag:2721/Service1.svc'.
Protocol bindings are configured at
the Site level in IIS or WAS
configuration.
Source Error:
An unhandled exception was generated
during the execution of the current
web request. Information regarding the
origin and location of the exception
can be identified using the exception
stack trace below.
Stack Trace:
[InvalidOperationException: No
protocol binding matches the given
address
'http://win-xqawq222tag:2721/Service1.svc'.
Protocol bindings are configured at
the Site level in IIS or WAS
configuration.]
System.ServiceModel.Channels.TransportChannelListener.OnOpening()
+11513378 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan
timeout) +229
System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan
timeout) +72
[InvalidOperationException: The
ChannelDispatcher at
'http://win-xqawq222tag:2721/Service1.svc'
with contract(s) '"Service1"' is
unable to open its IChannelListener.]
System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan
timeout) +118
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan
timeout) +261
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan
timeout) +107
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan
timeout) +261
System.ServiceModel.HostingManager.ActivateService(String
normalizedVirtualPath) +121
System.ServiceModel.HostingManager.EnsureServiceAvailable(String
normalizedVirtualPath) +479
[ServiceActivationException: The
service '/Service1.svc' cannot be
activated due to an exception during
compilation. The exception message
is: The ChannelDispatcher at
'http://win-xqawq222tag:2721/Service1.svc'
with contract(s) '"Service1"' is
unable to open its IChannelListener..]
System.ServiceModel.AsyncResult.End(IAsyncResult
result) +11531006
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult
result) +194
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication
context, Boolean flowContext) +176
System.ServiceModel.Activation.HttpHandler.ProcessRequest(HttpContext
context) +23
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+181 System.Web.HttpApplication.ExecuteStep(IExecutionStep
step, Boolean& completedSynchronously)
+75
No protocol binding matches the given
address
'http://win-xqawq222tag:2721/Service1.svc'.
Protocol bindings are configured at
the Site level in IIS or WAS
configuration.
Further, I am able to hit the policy file at http://localhost/clientaccesspolicy.xml and http://[computerNameHere]/clientaccesspolicy.xml.
Is there something else I need to look at?

I freely admit I haven't exactely tried to reproduce you specific error, but I noticed something I too stubled over.
Colin Cole blogged that there was a subtle change in cap.xml format in regard to using SSL.
I didn't use SSL, but only when I changed
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
to
<allow-from http-request-headers="*">
<domain uri="http://*" />
<domain uri="https://*" /> <!-- if needed -->
</allow-from>
accessing the service worked.

I had to make the following change to the ServiceReferences.ClientConfig file and then publish again:
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_Service1">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost/Service1.svc" binding="customBinding"
bindingConfiguration="CustomBinding_Service1" contract="ServiceReference1.Service1"
name="CustomBinding_Service1" />
<!--<endpoint address="http://localhost:2721/Service1.svc" binding="customBinding"
bindingConfiguration="CustomBinding_Service1" contract="ServiceReference1.Service1"
name="CustomBinding_Service1" />-->
</client>
</system.serviceModel>
</configuration>

Related

Cross-domain error Silverlight + WCF

I have read most of the topics covering cross-domain error and still cannot get it working. Within the website, I load Silverlight module which communicates with WCF Webservice. On localhost, it works fine, no error occurred.
I have Webservice hosted on http://localhost:50283 and in the same folder that port 50283 refers to I have clientaccesspolicy.xml located which looks as follows
<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>
I placed clientaccesspolicy.XML hardly everywhere including \wwwroot but that brought no effect anyway. I can access clientaccesspolicy.xml both on local and on a different computer within the same network (http://computerIP:50283/clientaccesspolicy.xml displays content). I tried to intercept error in order to find out some more details about error's nature but fiddler does not enlist any error, the only browser does. Literally, I tried everything and still no change. Has anyone faced a similar issue and could provide some hints where I should seek for a solution?
I ran into similar topic with no solution as well, alas
Silverlight-to-WCF cross-domain exception, but clientaccesspolicy.xml is being read successfully
I remember running into this many years ago and solving it a bit differently, namely with a behavior. Consider the following:
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.Xml;
internal class CrossDomainServiceBehavior : BehaviorExtensionElement, IEndpointBehavior
{
private ServiceHost serviceHost;
public override Type BehaviorType
{
get { return typeof(CrossDomainServiceBehavior); }
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
if (serviceHost == null)
{
serviceHost = new ServiceHost(typeof(CrossDomainPolicyService));
string address = new Uri(endpoint.Address.Uri, "/").ToString();
ServiceEndpoint crossDomainEndpoint = serviceHost.AddServiceEndpoint(typeof(ICrossDomainPolicyService), new WebHttpBinding(), address);
crossDomainEndpoint.Behaviors.Add(new WebHttpBehavior());
serviceHost.Open();
}
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
protected override object CreateBehavior()
{
return new CrossDomainServiceBehavior();
}
}
internal class CrossDomainPolicyService : ICrossDomainPolicyService
{
public Message ProvideClientAccessPolicyFile()
{
XmlReader xmlReader = CreateClientAccessXml();
return Message.CreateMessage(MessageVersion.None, string.Empty, xmlReader);
}
public Message ProvideCrossDomainPolicyFile()
{
XmlReader xmlReader = CreateCrossDomainXml();
return Message.CreateMessage(MessageVersion.None, string.Empty, xmlReader);
}
private static XmlReader CreateClientAccessXml()
{
TextReader reader = new StringReader(#"<?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 XmlReader.Create(reader);
}
private static XmlReader CreateCrossDomainXml()
{
TextReader reader = new StringReader(#"<?xml version='1.0'?>
<cross-domain-policy>
<allow-http-request-headers-from domain='*' headers='*'/>
</cross-domain-policy>");
return XmlReader.Create(reader);
}
}
The CrossDomainServiceBehavior needs to be added to the behaviors on your WCF service and it uses the CrossDomainPolicyService for dynamically adding the cross domain policy. This prevents you from having to add the cross domain file to the website itself.
Adding the behavior from code (for example with self hosted services):
endPoint.Behaviors.Add(new CrossDomainServiceBehavior());
Or in case of WCF definitions in config:
For the sake of this example I will assume the CrossDomainServiceBehavior is in the namespace Services.CrossDomainServiceBehavior and the assembly it is located in is version 1.0.0.0 with a neutral culture. It also assumes you have a binding on your service declaration called webHttp.
Registering the behavior:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="CrossDomainServiceBehavior" type="Services.CrossDomainServiceBehavior, CrossDomainServiceBehavior.AssemblyName, Version=1.0.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
Declare the behavior:
<behaviors>
<endpointBehaviors>
<behavior name="CrossDomainServiceBehavior">
<webHttp/>
<CrossDomainServiceBehavior/>
</behavior>
</endpointBehaviors>
<behaviors>
Add the behavior to the binding (here as example one called webHttp):
<bindings>
<webHttpBinding>
<binding name="webHttp"
maxReceivedMessageSize="20000000" >
<security mode="None">
<transport clientCredentialType = "None"/>
</security>
</binding>
<CrossDomainServiceBehavior />
</webHttpBinding>
</bindings>
Finally, add the behavior to your service endpoint, here in example one that implements ISomeService:
<endpoint address="" binding="webHttpBinding" contract="Services.ISomeService" bindingConfiguration="webHttp" behaviorConfiguration="CrossDomainServiceBehavior "/>
Not sure if it has to do anything with it, but I have a similar setup and my clientaccesspolicy.xml looks a bit different.
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="SOAPAction">
<domain uri="http://*"/>
<domain uri="https://*" />
</allow-from>
<grant-to>
<resource include-subpaths="true" path="/"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Especially the splitting of http and https adresses is different.
Besides that you are trying to do this with a non-default port, have you tried it on the default port 80? oh and on the production environment those *'s are replaced with the actual domain name.

Sharepoint custom WCF Rest service not using maxReceivedMessageSize

I'm building custom WCF Rest service for Sharepoint 2010. Main task of service is to download and upload some files to/from Sharepoint. Download is working as expected, but when uploading file larger than 64Kb I get following error :
The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.
Stack trace :
System.ServiceModel.Channels.HttpInput.ThrowHttpProtocolException(String message, HttpStatusCode statusCode, String statusDescription)
System.ServiceModel.Channels.HttpInput.ThrowMaxReceivedMessageSizeExceeded()
System.ServiceModel.Channels.HttpInput.GetMessageBuffer()
System.ServiceModel.Channels.HttpInput.ReadBufferedMessage(Stream inputStream)
System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception& requestException)
System.ServiceModel.Channels.HttpRequestContext.CreateMessage()
System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
System.ServiceModel.PartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state)
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state)
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
So my first guess was to increase maximum message size through custom configuration as follows :
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Project.Poc.StorageServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Project.Poc.IStorageService" behaviorConfiguration="Project.Poc.StorageServiceBehavior">
<endpoint binding="webHttpBinding" bindingConfiguration="StreamedRequestWebBinding" contract="Project.Poc.IStorageService"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="StreamedRequestWebBinding"
sendTimeout="00:05:00"
openTimeout="00:05:00"
receiveTimeout="00:05:00"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
transferMode="StreamedRequest">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
After applying this, deploying my WSP and doing IIS reset error was still there. Same HTTP 400 with above information from WCF trace. So somehow my web.config configuration is not good because WCF service is not using it?
Upload files that are smaller then 64KB is working as expected.
Also this is My IStorageService.cs definition :
namespace Project.Poc
{
[ServiceContract]
public interface IStorageService
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "/Download?path={path}")]
Stream DownloadFile(string path);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/Upload?path={path}")]
void UploadFile(string path, Stream content);
}
}
And also StorageService.svc in ISAPI folder where my web.config is also :
<%# ServiceHost Language="C#" Debug="true" Service="Project.Poc.StorageService, Project.Poc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d2ed6a8d86479f52" CodeBehind="StorageService.svc.cs" Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
I tried every other variation of web.config that I found googling but with no luck. What can be cause of this? Any help is more than welcome.
Also if you need any other part of the source code, just let me know. I will update my question.
Thank you in advance!
I'd review your client config - to be sure binding configuration has same attribute
maxReceivedMessageSize="2147483647".
Also, I'd try to add to your bindings (both client and service)
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
If both of this will not help - try to use SvcTraceViewer to find out where the error comes from (client when sending, server, ...)

Windows service hosting a WCF service closing immediately

I tried hosting a WCF Library service with windows service project, I installed the service, however, when i start the service in services.msc, the service start and closses immediatly. Following the message that gets displayed:
The Servicel service on Local
Computer started and then stopped.
Some services stop automatically if
they are not in use by other services
or programs.
The App.config file for wcf and the windows service project is same and it is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- 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="WorkMateWCF.Service1">
<endpoint address="" binding="netTcpBinding" bindingConfiguration=""
contract="WorkMateWCF.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8523/WorkMate1" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
The entire project/solution is downloadable here: https://skydrive.live.com/?cid=d358d316fa2c3a37&sc=documents&uc=1&id=D358D316FA2C3A37%21135#
Could you please guide me on how to proceed further. Thank you.
Additional information:
Following is the code from the service1.cs file in windows service project.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using WorkMateWCF;
namespace WorkMateWinService
{
public partial class Service1 : ServiceBase
{
internal static ServiceHost MyServiceHost = null;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (MyServiceHost != null)
{
MyServiceHost.Close();
}
MyServiceHost=new ServiceHost(typeof( Service1));
MyServiceHost.Open();
}
protected override void OnStop()
{
if (MyServiceHost != null)
{
MyServiceHost.Close();
MyServiceHost = null;
}
}
}
}
What I find very confusing (and probably the .NET runtime, too) is the fact that your Windows Service is called Service1, while your WCF Service also is called Service1 (without a namespace or anything).
So which of the two Service1 class types will be used here???
MyServiceHost = new ServiceHost(typeof(Service1));
I'm not sure - and I'm afraid it will be the wrong class (the Windows NT Service class).
You should give your stuff more meaningful names and keep those things apart (by name, too) !
Got the issue, when I reviewed my event logs I found this:
"Service cannot be started. System.InvalidOperationException: The HttpGetEnabled property of ServiceMetadataBehavior is set to true and the HttpGetUrl property is a relative address, but there is no http base address. Either supply an http base address or set HttpGetUrl to an absolute address.
at System.ServiceModel.Description.ServiceMetadataBehavior.EnsureGetDispatcher(ServiceHostBase host, ServiceMetadataExtension mex, Uri url, String scheme)
at System.ServiceModel.Description.ServiceMetadataBehavior.CreateHttpGetEndpoints(ServiceDescription description, ServiceHostBase host, ServiceMetadataExtension mex)
at System.ServiceModel.Description.ServiceMetadataBehavior.ApplyBehavior(ServiceDescription description, ServiceHostBase host)
at System.ServiceModel.Description.ServiceMetadataBehavior.System.ServiceModel.Description.IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescript..."
Then after thorough reviewing, the issues is that I did HTTPSGETENABLED to false only for one, infact there are two, after making the change for the other one, the app started to work like charm.
I special

Accessing self hosted WCF service from Silverlight 4

I have a self hosted WCF 4 service, catering the same contract via basicHttpBinding for Silverlight 4 clients and wsHttpBinding for the others. The code is very short and simple and provided here.
I get the following error when trying to access the a service method from WCF:
Message=An error occurred while trying to make a request to URI
http://localhost:8008/WCF4Silverlight.MyService/SL. 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.
I do have the method, GetClientAccessPolicy() serving the cross-domain policy using WebGet attribute, and I am kind of sure that there is a problem with it getting exposed properly. Your insight into the problem will be highly appreciated. If I type http://localhost:8008/WCF4Silverlight.MyService/clientaccesspolicy.xml in the browser, I do get the xml for the same, but the call from Silverlight always fails with the above error.
Here is the code for the WCF service:
namespace WCF4Silverlight
{
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface IClientAccessPolicy
{
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
Stream GetClientAccessPolicy();
}
}
namespace WCF4Silverlight
{
public class MyService: IMyService, IClientAccessPolicy
{
public Stream GetClientAccessPolicy()
{
const 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>";
if (WebOperationContext.Current != null)
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml"; return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
}
//Other service methods....
}
Here is code that publishes the service:
class Program
{
static void Main(string[] args)
{
ServiceHost myServiceHost = new ServiceHost(typeof(MyService));
myServiceHost.Open();
//Wait for client action.
myServiceHost.Close();
}
}
Here is the app.config for the WCF service host:
<service name="WCF4Silverlight.MyService" behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8008/MyService/"/>
</baseAddresses>
</host>
<endpoint address="general" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyService" contract="WCF4Silverlight.IMyService"/>
<endpoint address="SL" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_IMyService" contract="WCF4Silverlight.IMyService"/>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBinding_IMyService" behaviorConfiguration="webHttpBehavior" contract="WCF4Silverlight.IClientAccessPolicy" />
</service>
And here is the ServiceReferences.ClientConfig for the Silverlight client:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
<customBinding>
<binding name="WSHttpBinding_IMyService">
<textMessageEncoding messageVersion="Default" writeEncoding="utf-8" />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:8008/MyService/SL"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="myWCFService.IMyService" name="BasicHttpBinding_IMyService" />
</client>
</system.serviceModel>
This is what I did to resolve the issue:
1) Used Fiddler to see where the WCF calls were directed. Fiddler told that the calls were failing to HOST - http:/localhost:8008 and URL - /clientaccesspolicy.xml.
2) Created a different class ClientAccessPolicy implementing IClientAccessPolicy (with WebGet for /clientaccesspolicy.xml).
3) Added another section in app.config of the host for a new service hosting the Clientaccesspolicy class. This one had its base address as http:/localhost:8008/
<service name="WCF4Silverlight.ClientAccessPolicy" behaviorConfiguration="ClientAccessPolicyBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8008/"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBinding_IMyService" behaviorConfiguration="webHttpBehavior" contract="WCF4Silverlight.IClientAccessPolicy" />
</service>
4) In the hosting code, created another instance of ServiceHost and launched the new service with Clientaccesspolicy
ServiceHost clientAccessPolicyHost = new ServiceHost(typeof(ClientAccessPolicy)); clientAccessPolicyHost.Open();
5) In the Silverlight client, deleted the existing reference to the WCF and added the one to the newly hosted service.
The WCF calls from Silverlight are now going through.
Self hosted services on machines without IIS where the clientaccesspolicy can't be served up from the root, can instead use this method to dynamically serve up the policy on Port 80:
http://blogs.msdn.com/b/carlosfigueira/archive/2010/07/25/enabling-cross-domain-calls-for-sl-apps-on-self-hosted-tcp-services.aspx
The easiest way to debug this kind of issues is by using Fiddler (www.fiddler2.com) to intercept the HTTP traffic. You'll immediately see if clientAccessPolicy.xml is requested, where it is expected to be, and what is the result.
If you get a 404 (resource not found) the file is not at the expected location (but your webGet annotation looks good to me), otherwise the issue is within the xml itself.
This is a very permissive clientAccessPolicy.xml that I usually use for development/testing purposes:
<?xml version="1.0" ?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
If you're using a self-hosted web service, you need to throw your ClientAccessPolicy.xml into the root of a website that can be reached on port 80 of your machine (e.g., http://localhost:80/ClientAccessPolicy.xml). This was new in Silverlight 4, and unfortunately, I haven't found it clearly explained in the MS docs. (It's mentioned, but it's not terribly clear.)

Subscribing to TFS events and WCF

Sorry for asking a question about something I don't know much about, but I've been pulling my hair out trying to get this working.
So, I have a WCF service that is hosted on IIS and seems to be working insomuch that I can "see" it on the network by going to http://servername/MyService.svc in a browser.
That .svc looks like:
<% #ServiceHost Service="Foo.Bar" %>
The relevant code looks like:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06Services/Notification/03")]
public interface IBar
{
[OperationContract(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*")]
[XmlSerializerFormat(Style = OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml);
}
and:
public class Bar : IBar
{
public void Notify(string eventXml, string tfsIdentityXml)
{
// Just some test output to see if it worked
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "tfs.txt");
File.WriteAllText(path, tfsIdentityXml + eventXml);
}
}
That's all been built and the ensuing .dll put into the bin dir in the site root in IIS.
I now want to subscribe via bissubscribe.exe (or a similar method) to TFS check-in events. I tried doing something like:
bissubscribe /eventType CheckinEvent
/address http://servername/MyService.svc
/deliveryType Soap
/server mytfsserver
But nothing; it doesn't even look like there was log activity. So keeping in mind I know nothing about WCF, what am I doing wrong? I imagine the address param is one thing; am I not supposed to point it to the .svc?
I have created a blog post how you can use WCF in combination with the Event Services of TFS: http://www.ewaldhofman.nl/post/2010/08/02/How-to-use-WCF-to-subscribe-to-the-TFS-2010-Event-Service-rolling-up-hours.aspx
TFS 2010 and WCF 4.0 configurations are described below...
Method signature:
public void Notify(string eventXml) /* No SubscriptionInfo! */
Web config:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="Microsoft.TeamFoundation, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
</assemblies>
</compilation>
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="NotificationServiceBehavior" name="TF.CheckinListener.CheckinListener">
<endpoint address="Notify" binding="wsHttpBinding" bindingConfiguration="noSecurity" contract="TF.CheckinListener.ICheckinListener" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="NotificationServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
</binding>
<wsHttpBinding>
<binding name="noSecurity" maxBufferPoolSize="20000000" maxReceivedMessageSize="200000000">
<readerQuotas maxStringContentLength="200000000" maxArrayLength="200000000" />
<security mode="None" />
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Subscription address for bissubscribe:
http://MachineName/VirtualDirectoryName/Service.svc/Notify
One point that jumps out is the fact you have a method that doesn't return anything except void. Those should be marked as "one-way" method in WCF:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06Services/Notification/03")]
public interface IBar
{
[OperationContract(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*", IsOneWay=true)]
[XmlSerializerFormat(Style = OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml);
}
Add the "IsOneWay=true" to your [OperationContract] attribute.
Other than that, there's nothing obviously wrong in your code, but to really tell, we'd need a lot more config info to really tell. Try the IsOneWay=true first and see if that solves your issue.
How is your service configured? In particular, is it configured to use basicHttpBinding?
Try creating a client to call your service to make sure it can be called.
Then, see if there's an example service from the TFS SDK - see if you can get the example to work.
I was able to complete this connection with the following:
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
public interface ITeamSystemObserver : IObservable
{
[OperationContract( Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", ReplyAction = "*" )]
[XmlSerializerFormat(Style=OperationFormatStyle.Document)]
void Notify(string eventXml, string tfsIdentityXml, SubscriptionInfo SubscriptionInfo);
}
Note you are missing the SubscriptionInfo parameter. Here is my web.config:
<basicHttpBinding>
<binding name="TfsEventServiceBasic">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>