I have a Class Library project that contains a WCF client: the configuration and a lot of logic associated with it.
This DLL will be used by multiple client applications that have to consume exactly the same contract.
The issue is that the config resides in the DLL, but each client application has different endpoint address and client certificate.
How can I "inject" values from the client application into the attributes with '????????' value in the DLL's config?
<endpoint address="????????"
binding="customBinding"
bindingConfiguration="NewBinding0"
name="yyyy"
contract="bbbbb" />
...
<behavior name="TestBehavior">
<clientCredentials>
<clientCertificate storeLocation="LocalMachine" storeName="My"
x509FindType="FindByThumbprint" findValue="????????" />
</clientCredentials>
</behavior>
...
Thanks :)
The config file in your DLL project will be used by Visual Studio, for example when updating service references: it isn't used at runtime.
Each client application that uses the DLL will need to have its own configuration file with the relevant configuration section in order to use the service at runtime.
Related
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.
I'm currently investigating WCF for implementing a RESTful service that will run through IIS.
Currently our software offers the ability to authenticate users against a range of sources
Our own internal user accounts stored in the database
A specified windows active directory where if authentication is
successful, a lookup is done to find which internal account the
winows one is linked to
Another LDAP server e.g Novell
So the way I want this to work is that a client sends an http(s) request with an
authentication header (basic for now) over SSL, then the service will use custom
authentication to implement the process described above.
For the moment I am self-hosting the service and trying to get the custom authentication
example working, it starts up correctly but all I get when I try to make a request from a browser
or a tool where i can attach an authentication header is
"Error 101 (net::ERR_CONNECTION_RESET): The connection was reset."
I have set a breakpoint in the custom authentication class an it is never reached, so I'm guessing its a problem with the
configuration.
My app.config;
<configuration>
...
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="secure">
<security mode="Transport">
<transport clientCredentialType="Basic"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="CELCAT.RegisterMarker.RegisterMarker" behaviorConfiguration="myServiceBehavior">
<endpoint address="https://mymachine:8001/servicename"
binding="webHttpBinding"
bindingConfiguration="secure"
contract="myServiceContract" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True"/>
<serviceAuthorization serviceAuthorizationManagerType="MyServiceAuthorizationManager, authenticatonassembly" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="servicenamespace, serviceassembly" />
<serviceCertificate findValue="certname"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I have read a post that said what I am trying to do is impossible out of the box with WCF
and to achieve this I will need to write a custom module or request interceptor as describe below;
authentication via custom module;
http://custombasicauth.codeplex.com/
authentication via request interceptor;
http://www.codeproject.com/KB/WCF/BasicAuthWCFRest.aspx
This seems like it should be possible to me, so my questions are
Is what i'm trying to do possible?
If so what have I got wrong? or if not which work around is best?
OK after much googling and prompting from Andrew Church (Thanks Andrew) I've figured this out.
The problem was although I had generated a certificate, I hadn't bound it to a port. Steps to help generate certificates and binding them can be found at;
http://www.codeproject.com/Articles/24027/SSL-with-Self-hosted-WCF-Service
This however asks you to use httpcfg, this tool doesn't exist on Windows Vista or 7 (my OS), so a further Google revealed this article;
http://msdn.microsoft.com/en-us/library/ms733791.aspx
Which tells me to use netsh, perfect! Well not quite, because this requires a parameter called appid, I didn't know where I could find this so a further search lead back here;
What appid should I use with netsh.exe?
So I followed all of the steps, commented out the certificate part of my app.config and hey presto I hit my break point in the custom config.
Hope this helps anyone else with the same problem
I am not sure whether this will work, but what I've done in the past is use a custom HTTP module. Our API uses access tokens, so we use the module to inspect headers for the presence of a token, if it doesn't exist we redirect to an Authentication endpoint in the api. The endpoint expects Basic authentication. Hope this helps.
I am trying to host a simple application with one .aspx, .asmx and .svc file each. I followed the below guide to achieve the hosting (since I am very new to the linux world, it took a while to understand it!):
http://www.mono-project.com/Mod_mono#Manual_Mod_Mono_Configuration
After all the hosting, I am able to access the aspx and asmx file. But when I try to access the svc file, I get the below error:
The ServiceHost must have at least one application endpoint (that does not include metadata exchange endpoint) defined by either configuration, behaviors or call to AddServiceEndpoint methods.
or
HttpListenerContext does not match any of the registered channels
I do have a pretty straight forward service endpoint defined in my web.config which looks like below:
<system.serviceModel>
<services>
<service name="TestWCFService">
<endpoint address="http://localhost/MonoTest/TestWCFService.svc" binding="basicHttpBinding"
contract="MonoTest.ITestWCFService"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
Can you please tell me what I am doing wrong?
Note: I used MS VS 2010 to create this project and then published it. The published directory is copied to the Apache/Linux Environment. The WCF doesn't make use of any complex type. I am using Mono Version 2.8.2
UPDATE
Update: I tried using 2.10.2 Mono. This error is gone and I am now facing a new one:
XmlSchema error: Named item http://tempuri.org/:DoWork was already contained in the schema object table. Consider setting MONO_STRICT_MS_COMPLIANT to 'yes' to mimic MS implementation. Related schema item SourceUri: , Line 0, Position 0.
After weeks of R&D on this I have figured out this. For some reason, I can't get the service WSDL to work (meaning I can't access the .svc from browser). However, the service works fine when I try to access it using Channel Factory.
So I have implemented everything in Channel Factory (for my Silverlight app) and everything seems to be working fine right now. I am still not sure how to get WSDL to work but that's not too important to me as of now.
I currently have a WCF service running in IIS7 and I have have added impersonation on each of the public web methods with the following:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void TestMethod(){}
When ever I call this method from my test client application I get the following error:
Could not load file or assembly 'System.Data.OracleClient, Version=4.0.0.0, Culture=neutral, PublicKeyToken=waeraewrar' or one of its dependencies. Either a required impersonation level was not provided, or the provided impersonation level is invalid.
I'm currently using Microsoft Enterprise Library 3.1, and .Net 4.0.
Sample code:
WcfService client = new WcfService();
client.TestMethod();
Try configuring the client to allow an impersonation level of impersonation. For example:
<system.serviceModel>
<client>
<endpoint address="http://xxxxx/Services/xxService.svc"
binding="wsHttpBinding"
contract="IServiceContract"
behaviorConfiguration = "ImpersonationBehavior" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel = "Impersonation" />
</clientCredentials>
</behavior>
<endpointBehaviors>
</behaviors>
</system.serviceModel>
See this article for more on impersonation and delegation.
The error message suggests that the problem is that the impersonating user doesn't have access to the System.Data.OracleClient assembly DLL in the file system, and thus can't load it.
Can you not cause the System.Data.OracleClient assembly to be first loaded by code outside the service methods requiring impersonation... i.e. by code running with the IIS worker process identity. For example in your service instance constructor.
Once the assembly is loaded into the service's AppDomain, the service methods running under impersonation shouldn't need to do so again.
My service can work with normal WCF calls, but to expose metadata (the wsdl file) I have to change configuration in such a way the normal WCF host fails.
I've spend countless hours on google trying to solve this, big problem there is that hosting a service inside a website is never discussed (yes this is different).
requirements:
Runs in an existing web site
Use sessions
Operable with Java, and as much .net versions as possible.
Expose metadata (wsdl will be enough)
edits:
IIS cannot be used
I'm using .NET 4 and WCF 4.
In this configuration the metadata can be reached (through the wsdl file) but when trying to host the normal wcf endpoints I get and InvalidOperationException:
Could not find a base address that matches scheme http for the endpoint with binding WSHttpBinding. Registered base address schemes are [].
So the base address is ignored.
But when I supply full addresses to the endpoints (simply copy the base address in front of the current address) the normal WCF calls work fine, but when trying to access metadata I get the following error:
No protocol binding matches the given address 'http://localhost:8080/Functionality'.
Protocol bindings are configured at the Site level in IIS or WAS configuration.
Here is the web.config serviceModel section, I made a small test web site just for testing this, but it would be to much to post all of it here, if you send me a pm though I will e-mail it to you.
<system.serviceModel>
<services>
<service behaviorConfiguration="metadataSupport" name="MyStuff.TestWithMetadata">
<endpoint address="Functionality" binding="wsHttpBinding" name="FunctionalityBinding"
contract="MyStuff.ITestWithMetadata" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="metadataSupport">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="metadataSupport">
<!--Navigate with browser to httpGetUrl for the wsdl file-->
<serviceMetadata httpGetEnabled="true" httpGetUrl="Metadata" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false">
<serviceActivations>
<add relativeAddress="TestWithMetadata.svc" service="MyStuff.TestWithMetadata" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
If anyone has any ideas on how to solve this, please help out.
When you host your service in IIS (which I assume from your requirement "Runs in an existing web site"), then your base address in the config is moot - it will not be used at all.
When hosting in IIS, your service address is determined by:
your server name
possibly a port number
the virtual directory (and possibly subdirectories thereof) where the *.svc file lives
the *.svc file itself (including extension)
So it might be something like:
http://MyServer:7777/ExistingWebApp/TestWithMetadata.svc
or whatever it is that you have in your case.
You seem to be using .NET 4 and WCF 4 (never mentioned that.....) and in that case, you could skip the *.svc file altogether by adapting your config entry:
<serviceHostingEnvironment multipleSiteBindingsEnabled="false">
<serviceActivations>
<add relativeAddress="MyService" service="MyStuff.TestWithMetadata" />
</serviceActivations>
</serviceHostingEnvironment>
In this case, the value of relativeAddress= becomes the service address (within the virtual directory this web.config lives in) - so your service address would be something like:
http://MyServer:7777/ExistingWebApp/MyService
No need for a *.svc file at all in this situation.
Turned out I should use httpGetUrl link to get the metadata, instead of the .svc file, with that the base address can be ignored.
I also moved this test stuff to the actual web site and got tons of problems with zero endpoints being loaded. That was caused by the service reference in serviceActivations not set to the full service name (needs to have namespace included).
I accepted marc's answer because he did help me along and to prevent this question from popping up in unanswered.