Unit Testing WCF ServiceHost fails within a TFS Integration Build - wcf

I have a problem related to creating an instance of a WCF ServiceHost withing a set of unit tests and a project that is build within an integration build in TFSBuild. The code used in the unit test is:
[TestMethod]
public void Service_Can_Be_Dynamically_Hosted()
{
ServiceHost host = new ServiceHost(typeof(DiscoveryService));
host.Open();
host.Close();
}
The configuration for the service, although it can be created through code directly, is located in an .config file containing the following details:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="TappingBoard.Core.Network.DiscoveryServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="TappingBoard.Core.Network.DiscoveryServiceBehavior"
name="TappingBoard.Core.Network.Services.DiscoveryService">
<endpoint address="" binding="wsHttpBinding" contract="TappingBoard.Core.Network.Services.IDiscoveryService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8001/TappingBoard/DiscoveryService/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
The unit test is working perfectly in the client machines with both administrator users and non-admin users executing the tests locally. In the case of the TFS Build Server, the user that is launching the Build is called TFSBuild and is member of Domain Users and a local Administrator in the TFS Build Server.
Executing the same unit test in the Build Server launches the following exception:
System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8001/TappingBoard/DiscoveryService/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details). ---> System.Net.HttpListenerException: Access is denied
As the TFS Build Server is using port 80 to expose some reports and webs over IIS, I changed the port to be used by the WCF Service to 8001. It didn't worked before with port 80 either.
Is there any option to have this test run on the TFS Build Server? Should I configure anything extra on my build?
In terms of providing the most useful information, the systems used are:
Dev Machines: VS2010TS, Windows 7RTM
Server Machines: TFS2010, Windows Server 2008 R2 RTM
Thanks in advance for your time and support.
Bests,
Miguel.

had the same problem a while back.
the solution I use is to manually register the http namespace once. Paul Wheeler has an excellent tool for that: HttpNamespaceManager
so from your code:
register "http://localhost:8001/TappingBoard/DiscoveryService/" and give the user which runs the unit-tests full access.
hope this helps!

This sounds like an issue with UAC. Even if your TFSBuild account is a local administrator, the process will not have Administrator privileges unless explicitly configured to have it.
I've run into this issue many times on my local box (Vista x64), and it has always been related to lack of Administrator rights. I can't tell you why it works in non-admin mode on your dev boxes, but then again I don't know how Win7 works in this regard.
An alternative to running the process with Administrator privileges is to configure the port in advance using netsh.

The exception happens when the system tries to register the url.
The url is registered with WAS (Windows Activayion Services). Could there be a problem that WAS is not set up.
There may be a more helpfull message in the event log.

Related

Adding webHttpBinding endpoint to an existing netTcpBinding

I have a working service which exposing netTcpBinding at the following way:
<service name="MetaData.Service.MetaDataServices" behaviorConfiguration="MetaDataServiceBehavior">
<endpoint address="net.tcp://localhost:5200/MetaDataService" binding="netTcpBinding" bindingConfiguration="MetaDataBinding" contract="MetaData.ServiceContract.IMetaDataService"/>
</service>
How can I add http endpoint? I tried the following:
<service name="MetaData.Service.MetaDataServices" behaviorConfiguration="MetaDataServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:5280/MetaDataService"/>
</baseAddresses>
</host>
<endpoint address="net.tcp://localhost:5200/MetaDataService" binding="netTcpBinding" bindingConfiguration="MetaDataBinding" contract="MetaData.ServiceContract.IMetaDataService"/>
<endpoint address="" binding="webHttpBinding" contract="MetaData.ServiceContract.IMetaDataService"/>
</service>
</services>
but got an exception:
HTTP could not register URL http://+:5280/MetaDataService/. Your
process does not have access rights to this namespace (see
http://go.microsoft.com/fwlink/?LinkId=70353 for details). class name:
RemoteProxy method name: Create
Unless you're running the self-hosted process as an administrator (which I'm guessing is not the case, and you have a good reason for that), you won't be able to start listening to HTTP requests in the machine. You'll need to use an administrator command prompt to grant access to your user account to do that, by following the instructions in the page linked in the error message (the link was broken, but it has just been fixed).
If you are running Windows 7/8/10/Vista/Server 2008, you can use the following command (from an administrator command prompt):
netsh http add urlacl url=http://+:5280/MetaDataService/ user=DOMAIN\user
Where DOMAIN\user is the user account you're running the process as. You can find it by using the command whoami in the command prompt.
Once you do that (only once per machine), then you should be able to run it with a non-admin account.

Simplest Console Hosted WCF Service generates a 404 when browse to it

I have the very simplest Console based host for a simple WCF service. The app config for the service is:
<system.serviceModel>
<services>
<service name="MagicEightBallServiceLib.MagicEightBallService"
behaviorConfiguration="EightBallServiceMEXBehavior">
<endpoint address=""
binding = "basicHttpBinding"
contract = "MagicEightBallServiceLib.IEightBall" />
<!-- Enable the MEX endpoint-->
<endpoint address="mex"
binding ="mexHttpBinding"
contract ="IMetadataExchange" />
<!--Need to add this so MEX knows the address of our service -->
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/MagicEightBallService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="EightBallServiceMEXBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
The host program shows its running perfectly:
** Console Based WCF Host *
***** Host Info ******
Address: http://localhost:8080/MagicEightBallService
Binding: BasicHttpBinding
Contract: IEightBall
Address: http://localhost:8080/MagicEightBallService/mex
Binding: MetadataExchangeHttpBinding
Contract: IMetadataExchange
**************************************************
The service is ready
When I attempt to browse to or generate a proxy I get:
HTTP Error 404.0 - Not Found
I can't figure out what's wrong. You can't get any simpler than this!
I have faced the same problem when reading Troelsen's book and could not find any answer online. Anyway it seems that the problem is in the project type for MagicEightBallLib. Troelsen suggests that you create a Visual C# -> Windows -> Class Library project, but he does not explain what modifications you need to make for it to work. If you instead use the Visual C# -> WCF -> WCF Service Library project, it will automatically start the WcfTestClient.exe, and add new tab in project's Preferences called "WCF Options". I tried to compare the differences between .csproj files for both types of projects but there is just too many.
So the solution is to just start with the WCF Service Library project type instead of Class Library, and adjust names of interfaces and classes so they fit what is in the book.
If anyone knows which particular parts of the .csproj file are responsible for enabling this, I'd very much like to hear about it.
Hope this helps.
Instead of using localhost:8080 use 127.0.0.1:8080. That's how I got the example to work on my windows 10 machine.

Azure WCF Service Consume Azure WCF Service

I current have a solution with an Azure WCF service and a Windows Phone 7 project. I can run the development fabric locally and browse to the url (http://127.0.0.1:81/API/V1.svc) of my service fine. When I do Add Service Reference from the Windows Phone application it will discover the service fine, but when I try to view the methods on the service I get the error "Unable to launch the ASP.NET Development Server because port '50149' is in use." If I click OK I get "There was an error downloading metadata from the address. Please verify that you have entered a valid address."
I don't quite understand why it is discovering it on port 50149 since I browse to it on port 81 but I tried using port 81 when adding the service and I got
There was an error downloading 'http://localhost:81/API/V1.svc'.
Unable to connect to the remote server
No connection could be made because the target machine actively refused it 127.0.0.1:81
Metadata contains a reference that cannot be resolved: 'http://localhost:81/API/V1.svc'.
There was no endpoint listening at http://localhost:81/API/V1.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
Unable to connect to the remote server
No connection could be made because the target machine actively refused it 127.0.0.1:81
If the service is defined in the current solution, try building the solution and adding the service reference again.
Here is my service model section
<system.serviceModel>
<services>
<service name="DocDemon.API.V1">
<endpoint name="basicHttpBinding" binding="basicHttpBinding" contract="DocDemon.API.IV1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
</bindings>
</system.serviceModel>
Do I need to defined and end point in here?
Does it have something to do with the WP7 project and the Azure WCF being in the same solution? (Do I have to have the WCF running when I trying to add service reference from the WP7 app?)
I moved the WP7 Application into its own solution and then it was able to detect the web service fine when that application was running in the local DevFabric. The WP7 application was just unable to find it when they were in the same solution.
Have you looked at the WCF Azure Samples known issues on the MSDN Code Gallery? There's a subtlety around metadata and a behavior tweak needed. Hopefully this helps.
In my WCF running in Azure I configure endpoints in two places (my example defines a secure ssl endpoint on port 443):
1st time in web.config to define endpoints contracts:
<system.serviceModel>
<services>
<service
behaviorConfiguration="CustomValidationBehavior"
name="ServiceName">
<endpoint
binding="wsHttpBinding"
bindingConfiguration="MembershipBinding"
name="bindingName contract="InterfaceName" />
Afterwards, you also must make sure that Azure exposes your service thru its own endpoints in ServiceDefinition.csdef:
<InputEndpoints>
<InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="CertName" />
</InputEndpoints>
You cannot use a reference to that port if it is not running, no metadata will be found.
I would say move your server project to IIS instead of Casini since that's where it'll run while on the Azure platform.
I did have some issues playing with Azure and Casini that did not happen on IIS.

Local service (The server has rejected the client credentials.)

I have a simple setup, a WPF application running on the machine and a WCF service hosted within a Windows Service on the same machine (always on the same machine). When i debug on one computer i can easily access the local WCF Service. When i run it on another machine i get an error:
"The server has rejected the client credentials."
Some of my observations are, that at my local machine i have no domain/network. Its my home machine. When at a customers site, it will not run, and gives the above error. Anyone got any ideas on why this is different on these computers?
/Brian
Edit:
Contract:
[ServiceContract(Namespace = "http://www.greenweb.dk/motiondetection")]
public interface IMotionDetection
{
[OperationContract]
bool GetMotionDetected();
}
App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings />
<client />
<services>
<service name="GreenWebPlayerMotionDetectionService.MotionDetected" behaviorConfiguration="MotionDetectionBehavior">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/GreenWebMotionDetectionService/"/>
</baseAddresses>
</host>
<endpoint address="" contract="GreenWebPlayerMotionDetectionService.IMotionDetection" binding="netNamedPipeBinding"/>
<endpoint address="mex" contract="IMetadataExchange" binding="mexNamedPipeBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MotionDetectionBehavior">
<serviceMetadata httpGetEnabled="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Edit 2
Security will not be a problem, no security is neeed, the computer on which it runs is already isolated from everything else.
EDIt 3
Have set <security mode="None"></security> on both the client and the server, now im getting this error: "There was an error reading from the pipe: Unrecognized error 109 (0x6)"
I can't figure out whether this is a step in the right direction
The problem seems to be the security. Instead of None i set the client and server to be "EncryptAndSign". This however wasnt enough when the host was a windows service. I abandoned the windows service approach and hosted it in a windows application instead - then it worked immediately...go figure!
The issue is with the
netNamedPipeBinding
.This binding is used to communicate inside a machine. Please check the link.Its for on-machine .
If you want to communicate between 2 machine which uses .net select net.tcp .If you want to communicate between .Net and Java apps use basicHttpBinding.
http://msdn.microsoft.com/en-us/library/system.servicemodel.netnamedpipebinding.aspx

How do I call a WCF webservice from Silverlight?

I am trying to call a WCF webservice (which I developed) from a Silverlight application. For some reason the Silverlight app does not make the http soap call to the service. I know this because I am sniffing all http traffic with Fiddler (and it is not a localhost call).
This my configuration in the server relevant to WCF:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service behaviorConfiguration="ServiceBehavior" name="Service">
<endpoint address="" binding="basicHttpBinding" contract="Service"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
And the ServiceReferences.ClientConfig file in the silverlight app (i am using the beta 2):
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_Service" maxBufferSize="65536"
maxReceivedMessageSize="65536">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://itlabws2003/Service.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_Service" contract="Silverlight_organigram.DataService.Service"
name="BasicHttpBinding_Service" />
</client>
</system.serviceModel>
This is the silverlight method that calls the service, I paste the whole method for copleteness, the lambda is to make the call synchronous, I have debugged it and after the line client.GetPersonsAsync(), Fiddler does not show any message travelling to the server.
public static List<Person> GetPersonsFromDatabase()
{
List<Person> persons = new List<Person>();
ServiceClient client = new ServiceClient();
ManualResetEvent eventGetPersons = new ManualResetEvent(false);
client.GetPersonsCompleted += new EventHandler<GetPersonsCompletedEventArgs>(delegate(object sender, GetPersonsCompletedEventArgs e)
{
foreach (DTOperson dtoPerson in e.Result)
{
persons.Add(loadFromDto(dtoPerson));
}
eventGetPersons.Set();
});
client.GetPersonsAsync();
eventGetPersons.WaitOne();
return persons;
}
Does anyone have any suggestions how I might fix this?
If the Silverlight application is not hosted in the same domain that exposes the Web service you want to call, then cross-domain restrictions applies.
If you want the Silverlight application to be hosted in another domain than the web service, you may want to have a look on this post to help you to have a cross domain definition file, or to write a middle "proxy" instead.
You wouldn't happen to be running from the filesystem would you? If you are serving up the silverlight application your local machine and not using the VS Web Server or IIS, you won't be able to make HTTP calls for security reasons. Similarly if you're loading from a web server, you can't access local resources.
Also I've found that Nikhil's Web Development Helper http://www.nikhilk.net/ASPNETDevHelperTool.aspx can be more useful than Fiddler because you will see local traffic as well, although it doesn't look like that is your issue in this case.
I am not 100% certain, but if you are running on Vista or Server 2008 you may have run into the User Access Control issue with http.sys
So in Vista and Win2k8 server, the HttpListener will listen only if you are running under a high privelege account. In fact, from my experience, even if you add yourself to the local administrators group, you might run into this issue.
In any case, try launching Visual Studio on Vista by Right Clicking and runas Administrator. See if that fixes it. If it does, you're good, but....
ideally you should run httpcfg
like:
httpcfg set urlacl -u http://itlabws2003 -a D:(A;;GX;;;yoursid)
your sid = the security identifier for the account you're running as, you can find it here:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
if you don't know it already, or you could possibly add yourself to BUILTIN\Administators, find the sid and run the httpcfg via command line again, specifying that sid.
User Access Control, Vista and Http.sys cause all this...if this is indeed the problem you are running into. Not sure but maybe its worth a try