How to deploy my WCF service on IIS 6.0? - wcf

I am completely new to WCF and deploying of services. I am having trouble setting up my service on IIS 6.0.
I need the exact steps to deploy my WCF service on IIS 6.0.
Note: I created a WCF service application...
So, what is the exact steps i need to follow to deploy my wcf service on IIS 6.0?

You have basically two options, I believe:
Option 1 - "bin" deploy (preferred option)
compile your WCF service into a DLL (class library)
create a website in IIS6
copy the WCF DLL's into the website's .\bin folder
create a *.svc file in that website
add an appropriate web.config in the website folder to define your endpoints and service configuration etc.
Your WCF service will now be reachable at the website's base address, plus the name of the *.svc file, e.g.
http://myserver/someweb/Myservice.svc
Your *.svc would look something like this:
<%# ServiceHost Language="C#" Debug="true"
Service="WCF_Simple_Service.HelloIndigoService" %>
The Service= attributes denotes the class implementing the service - fully qualified with its namespace.
Option 2 - put stuff into App_Code
create a website in IIS6
put all your WCF related *.cs files directly into the .\App_Code folder
create a *.svc file in that website
add an appropriate web.config in the website folder to define your endpoints and service configuration etc.
Your WCF service will now be reachable at the website's base address, plus the name of the *.svc file, e.g.
http://myserver/someweb/Myservice.svc
Your *.svc would look something like this:
<%# ServiceHost Language="C#" Debug="true"
Service="Service"
CodeBehind="~/App_Code/Service.cs" %>
A simple, sample web.config might look something like this:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WithDebug">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="SimpleWCF.HelloIndigoService" behaviorConfiguration="true">
<endpoint
address=""
binding="basicHttpBinding"
contract="SimpleWCF.IHelloIndigoService" />
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
You basically define your <service> tag - and again: the name= denotes the class implementing the service - fully qualified with its namespace. It must contain at least one endpoint - since IIS6 only support HTTP, you can use basicHttpBinding or wsHttpBinding and that's about all there is. A "mex" endpoint is optional - but very useful, especially for development and testing. It allows client to "discover" the service and get its service description so it can interface with it.
Once your service is deployed in IIS, you can see it in action using a tool like the WCF Test Client that ships for free with WCF, or SoapUI which is a general-purpose SOAP testing utility (with a free edition for you to use).

Related

How is WCF service connected to endpoints by default?

I have been provided a code base where a WCF service is hosted in IIS. The project uses development server, but that does not matter.
The web.config file contains only the following section for service configuration:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
The .svc file contains the following:
<%# ServiceHost Language="C#" Debug="true" Service="TestApp.MySvcClass" CodeBehind="MySvcClass.svc.cs" %>
MySvcClass implements the contract (ISvcContract).
The thing is, under .NET 4, this configuration works. There is no declaration anywhere that establishes the link between the contract and the service types, there is nothing that links the behaviors to service type, there is no end point declaration, and yet it works.
With .net 3.5, it does not. It complains about the configuration.
What is the default behavior for WCF service projects' configuration?
Where is it documented?
Can I force these type of settings to fail?
I did not have the time to test, but if I add another svc file, the project would probably go crazy, since things may magically fall into place for a single service, but I'd rather not have configuration processed in a smart way.
A Developer's Introduction to Windows Communication Foundation 4
Read the Simplified Configuration section. It lists out default endpoints, protocols, bindings, etc.

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.

How can I register a WCF service programmatically within an IIS environment

Let's say we have 2 projects with following layout
Project "web"
global.asax (I thought of this destination for registration within eg void Application_Start(System.Object sender, System.EventArgs e)
web.config
Project "wcf"
DemoService.cs
IDemoService.cs
web.config would look like this
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="fooBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="wcf.DemoService"
behaviorConfiguration="fooBehavior">
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<endpoint address=""
binding="wsHttpBinding"
contract="wcf.IDemoService" />
</service>
</services>
</system.serviceModel>
</configuration>
So ... now ... somewhere (as mentioned above I thought of global.asax) I need to register, that when browsing to URI wcf.DemoServiceget's resolved and for a mex-request the wcf.IDemoService gets resolved for reading the attributes to get a WSDL.
This would usually be done by creating a .svc file and put header in the first line, e.g.:
<%# ServiceHost Language="C#" Debug="true" Service="wcf.DemoService" %>
In e.g. a console application by
var serviceHost = new ServiceHost(typeof (wcf.DemoService));
serviceHost.Open();
And combine this with a host element within the service element to specify the URI - or use another ctor-overload of ServiceHost
But I would rather go for a static registration (or any web.config registration which works for IIS 7.5) - is this possible? If so, how?
WCF 4 (.NET 4.0) offers both code based registration of services and configuration based registration of services.
Code based configuration is achieved through ASP.NET Routing by new ServiceRoute:
RouteTable.Routes.Add(new ServiceRoute("DemoService",
new ServiceHostFactory(), typeof(wcf.DemoService));
Routes are usually used with REST services but it works for SOAP services as well.
Registering service in configuration is called configuration based activation. You will define virtual .svc file in web.config:
<serviceHostingEnvironment>
<serviceActivation>
<add relativeAddress="DemoService.svc" service="wcf.DemoService" />
</serviceActivation>
</serviceHostingEnvironment>
In both cases you are defining only relative path to your service because base address is always specified by your web site hosted in IIS.

MvcMiniProfiler profiling web app and lower layers

I have MiniProfiler set up and working in my ASP.NET MVC app. My controllers make calls via WCF to a BLL which in turn talks to the database. I would like to see profiling from the WCF service alongside the existing profiling I see from the web app. Is it a case of making MiniProfiler a parameter in all service calls?
In a recent release of the MvcMiniProfiler they added WCF support (version 1.8 or greater). This is a 3 step process to get this working:
Add References
First add references to the MvcMiniprofiler and MvcMiniProfiler.WCF in your UI layer and WCF layer via nuget (or download the source and compile your own).
Setup WCF Host
Second, within the web.config of the service host you have to add the miniprofiler as an endpoint behavior. All of the config sections belong in "configuration/system.serviceModel".
<endpointBehaviors>
<behavior name="miniProfilerBehavior">
<wcfMiniProfilerBehavior />
</behavior>
</endpointBehaviors>
Then add the behavior extension (Note the version number needs to match your version of the MvcMiniProfiler.WCF):
<extensions>
<behaviorExtensions>
<add name="wcfMiniProfilerBehavior" type="MvcMiniProfiler.Wcf.WcfMiniProfilerBehavior, MvcMiniProfiler.Wcf, Version=1.8.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
Then setup the endpoints to use the profiler behavior you setup:
<services>
<service behaviorConfiguration="BaseBehavior" name="BSI.Something">
<endpoint address="" behaviorConfiguration="miniProfilerBehavior" binding="basicHttpBinding" bindingConfiguration="http" contract="BSI.ISomething"/>
</service>
</services>
Depends on your setup but I had to add one more web.config setting to run all managed modules for all requests. This config is in the root "configuration" section:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
Setup WCF Client
Last, setup the wcf client to "turn on" the mvc profiler by doing much the same above.
Add the extension:
<extensions>
<behaviorExtensions>
<add name="wcfMiniProfilerBehavior" type="MvcMiniProfiler.Wcf.WcfMiniProfilerBehavior, MvcMiniProfiler.Wcf, Version=1.8.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
Add a behavior:
<behaviors>
<endpointBehaviors>
<behavior name="wcfMiniProfilerBehavior">
<wcfMiniProfilerBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
Setup the endpoints to use that behavior:
<client>
<endpoint address="http://something/Something.svc" behaviorConfiguration="wcfMiniProfilerBehavior"
binding="BasicHttpBinding" bindingConfiguration="BasicHttpBinding_HTTP"
contract="BSL.ISomething" name="BasicHttpBinding_ISomething" />
</client>
And you're done!
Side Note:
How does the MvcMiniProfiler actually work over WCF?
Basically the client behavior sets up a SOAP header that tells the wcf host to turn on the profiler. It passes that header along which is read by the endpoint behavior on the WCF host side. It then turns the profiler on in the host. Lastly when the WCF host is replying back to the client it stuffs all the profiler goodness into the SOAP response header which is in turn read by the WCF client. Pretty ingenious.
That's one method, but in order to get the reference to the libraries you would have to add references in the lower layers for MvcMiniProfiler anyway.
What I did in this very same situation is to take advantage of the global access point that MiniProfiler provides as a singleton. So, I just added the reference in the lower levels (deleted the stuff relative to MVC, such as the views) and just used MiniProfiler.Current as if I were on the upper layers.
It works like a charm. :)

WCF base address not found

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.