Programmatically configure and host WCF Service in IIS - wcf

How can i programmatically configure and host WCF Service in IIS. I have created my WCF service example /WCFServices/Service1.svc". I want to programmatically configure and host this service in IIS. Can anyone help me on this?

The class you want is Microsoft.Web.Administration.ServerManager
http://msdn.microsoft.com/en-us/library/microsoft.web.administration.servermanager(v=VS.90).aspx
It has methods for manipulating most aspects of IIS, for example, adding application pools and applications. for example, this code configures a new IIS application
//the name of the IIS AppPool you want to use for the application - could be DefaultAppPool
string appPoolName = "MyAppPool";
//the name of the application (as it will appear in IIS manager)
string name = "MyWCFService";
//the physcial path of your application
string physicalPath = "C:\\wwwroot\mywcfservice";
using (ServerManager serverManager = new ServerManager())
{
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");
ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();
ConfigurationElement siteElement = sitesCollection[0];
ConfigurationElementCollection siteCollection = siteElement.GetCollection();
ConfigurationElement applicationElement = siteCollection.CreateElement("application");
applicationElement["path"] = name;
applicationElement["applicationPool"] = appPoolName;
ConfigurationElementCollection applicationCollection = applicationElement.GetCollection();
ConfigurationElement virtualDirectoryElement = applicationCollection.CreateElement("virtualDirectory");
virtualDirectoryElement["path"] = #"/";
virtualDirectoryElement["physicalPath"] = physicalPath;
applicationCollection.Add(virtualDirectoryElement);
siteCollection.Add(applicationElement);
serverManager.CommitChanges();
}
In general, the calss is just a thin wrapper around the IIS config file. You can understand it by looking at your exisiting file, or even by looking at what you have to do in IIS Manager to configure the service manually, then translating that into the resulting configuration changes.
You can do all (at least lots of) the the IIS configuration in this way (e.g. configure application throttling, enable authentication schemes etc.).
The WCF part of the configuration is just normal WCF. you can do it either in code or in configuration.

What you are looking for is called Publish. You can find it from the right-click context menu on the WCF Service project. You can publish from there or create a package for publishing later or distributing it to a remote site. There are a lot of tutorials on the net.
If you have a specific question about this feature, feel free to ask.

Have a look at msdeploy, a command line packaging and deployment tool:
http://blogs.iis.net/msdeploy/
http://vishaljoshi.blogspot.de/2009/02/web-deployment-with-vs-2010-and-iis.html
http://msdn.microsoft.com/en-us/vs2010trainingcourse_webdevelopment_topic8#_Toc282089433

Related

using a wcf service with a custom config path

I am struggling with calling a WCF service inside an assembly library with a custom config file. The WCF service runs within a Citrix Xen Server environment which is probably the cause of the problem.
I have setup a console application that references the assembly library and calls a public method inside that library that connects to the WCF Service endpoint and display the data derived from a call of a WCF function inside a Win Forms Datagrid.
Right now I am setting the config path for the current app domain inside the constructor of the Win Forms class 'E2ADokumente' that is displayed by the assembly library:
var assembly = Assembly.GetAssembly(typeof(E2ADokumente));
var assemblyFilePath = assembly.Location;
var assemblyDirectory = Path.GetDirectoryName(assemblyFilePath);
var dllName = assembly.GetName().Name + ".dll.config";
string configPath = Path.Combine(assemblyDirectory, dllName);
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configPath);
The WCF proxy is build like so:
WSTrustChannelFactory channelFactory = new WSTrustChannelFactory("STSEndpunkt")
"STSEndpunkt" is the name of the endpoint and is defined in the config file.
All works if I run the code locally but the config file won't be located if I run the same app within the Terminal Services environment. The error messages states that "STSEndpunkt" cannot be found.
It works inside the Terminal Services environment though if I run the assembly library inside a new app domain. But having a separate layer and calling method through reflection is a little too much overhead so I am searching for a simpler solution.
How can I set the path for a config file with the WCF configuration details inside an Assembly library that runs within Terminal Services?
Building the WCF channel setup in code is not an option.
I found a solution after a lot of google-fu.
The setting of the config path for the assembly library works if its done inside the static constructor of the class.
static E2ADokumente()
{
var assembly = Assembly.GetAssembly(typeof(E2ADokumente));
var assemblyFilePath = assembly.Location;
var assemblyDirectory = Path.GetDirectoryName(assemblyFilePath);
var dllName = assembly.GetName().Name + ".dll.config";
string configPath = Path.Combine(assemblyDirectory, dllName);
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configPath);
}
After that the config file for the WCF service was loaded by the assembly library.
I have no idea what differences the fact that the application is running within Terminal Services contributes but at least this is a simple fix.

WCF Service in Silverlight Application

I have a Silverlight 5 application that is obtain data from a Silverlight-enabled WCF service in another project (my solution has a Silverlight project and a web project). There are a number of similar posts, but they're referring to web services hosted on a web server (proper web services).
I am aware that I have to tell the application where to find the service in both dev and prod. In dev, you'll have a port typically. My code to create a service client (with the correct EndpointAddress) is as such:
BasicHttpBinding binding = new BasicHttpBinding(
Application.Current.Host.Source.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase)
? BasicHttpSecurityMode.Transport : BasicHttpSecurityMode.None);
binding.MaxReceivedMessageSize = int.MaxValue;
binding.MaxBufferSize = int.MaxValue;
Uri tempUri = new Uri("../PolicyDataService.svc", UriKind.Relative);
EndpointAddress servAddr = new EndpointAddress(tempUri);
PolicyDataServiceClient temp = new PolicyDataServiceClient("BasicHttpBinding_PolicyDataService", servAddr);
return temp;
Now, where am I going wrong? In dev, everything works fine, but in prod the service is never being called. Thanks!
I'm not sure what's going on, but here are a few things that you can try if you haven't already:
Browse to the svc file on Prod and make sure you can access it (http://yoursite/PolicyDataService.svc)
Point your code to the prod location and make sure you can connect without any issue. Doing this will usually reveal what the problem is, provided you can connect.
Since you're using BasicHttpBinding, you shouldn't be running into security issues with the binding. I know this is pretty basic, but have to start somewhere.

WCF- how to add multiple services to Service.svc?

I have 4 services running via a service host project, which communicate fine with my asp.net application when the ASP.NET development server hosts them through VS for debugging.
I am trying to deploy these to IIS on a windows server 2008 machine, using WAS.
I have the project set up as an application in IIS, and have copied the entire config section from app.config in servicehost project to web.config of the IIS site.
After a few compliation issues, I now get a directory listing when i navigate to http://localhost:8000/Services
I have also created a Service.svc file, which contains
<%#ServiceHost Service=MyApp.AddressService %>
When I navigate to localhost:8000/Services/AddressService, I get a message that i've created a service, and appending ?wsdl gives me the xml to create a client.
Problem is, I get an error when I try to add any more services to the .svc file.
Should I be using service.svc to configure multiple services, or is there a different way using WAS?
How can I expose my other three services through the same application?
Thank you!
You cannot add multiple service to a SVC file. One SVC file = one service class. No way to change that.
However: you can definitely implement multiple service interfaces on your service class:
public class YourService : IService1, IService2, IService3
{
...
}
and then you have one SVC file = one service (implementation) class = 3 service contracts.
In .NET 4 / WCF 4, you'll be able to define URL's for service in your web.config, and you don't need the SVC files anymore.
See this blog post here or this one here for more info, if .NET 4 is an option for you.

Using a ReceiveActivity in a Sharepoint Workflow

I've made my first little workflow in sharepoint and I am trying to access it from the outside using a ReceiveActivity. I have created a WCF svc file with
and created a website in IIS with the same application pool as the sharepoint site.
Now I can start the workflow from my doclib, but when I try to reach the ReceiveActivity like below, I get the following error: "the workflow hosting environment does not have a persistence service as required by an operation on the workflow instance".
I think it has something to do with not using the Sharepoint persistence service in my own WCF website, but I'm not sure. Any idea's on this one???
DoMyThingContractClient proxy = new DoMyThingContractClient ();
IContextManager contextManager = proxy.InnerChannel.GetProperty<IContextManager>();
IDictionary<string, string> context = contextManager.GetContext();
context.Add("instanceId", myInstanceId);
contextManager.SetContext(context);
result = proxy.GetMyMethod(tb1.Text, tb2.Text);
Have you created the SQL tables that host the workflows? The ones at C:\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\en? If you did, you now need to add the required tags to your config (your WCF's folder with the svc file in this case) as explained at msdn.
Edit after comments: try to run a Persistance Service in your code:
SqlWorkflowPersistenceService ps = new SqlWorkflowPersistenceService("Initial Catalog=SqlPersistenceService;Data Source=localhost;Integrated Security=SSPI");
currentWorkflowRuntime.AddService(ps);

WCF / Silverlight Call Back to Server Fails in IIS

Using Silverlight 3, Windows XP, IIS 5.1, I've written a small app which uses the channel method of calling the server rather than the 'add service reference' as per this MSFT article.
The application opens and the call to the server work when running it on the development computer in VS 2008 using the address localhost plus the port number. When I change the address to the computer name, dellnov2006, and publish the application to IIS, the application opens, but the call to the web service does not work.
Watching the call in Web Dev Helper, I see that the app was trying to call the service file, http://dellnov2006/Service1.svc, and is getting a 404 error.
So far, I've:
-In IIS mapped the .svc type to aspnet-isapi.dll
-Run the utility CleanIISScriptMaps
-Run aspnet_regiis.exe -i –enable
Any help would be appreciated - I am running out of ideas on this.
--
Here is the call back to the server, and the contents of the Service1.svc file:
private void Button_Click(object sender, RoutedEventArgs e)
{
// create a custom binding that uses HTTP and binary encoding
var elements = new List<BindingElement>();
elements.Add(new BinaryMessageEncodingBindingElement());
elements.Add(new HttpTransportBindingElement());
var binding = new CustomBinding(elements);
// create a channel factory for the service endpoint configured
// with custom binding
//var cf = new ChannelFactory<IService1>(binding,
// new EndpointAddress("http://localhost:1042/Service1.svc"));
var cf = new ChannelFactory<IService1>(binding,
new EndpointAddress("http://dellnov2006/Service1.svc"));
// save the syncronized context for the ui thread
uiThead = SynchronizationContext.Current;
// open the channel
IService1 channel = cf.CreateChannel();
// invoke the method asychrnoously
channel.BeginGetPerson(4, GetPersonCallback, channel);
}
Here are the contents of the svc file for what they are worth:
<%# ServiceHost Language="C#" Debug="true" Service="SilverlightChannelApp1.Web.Service1" CodeBehind="Service1.svc.cs" %>
Many thanks
Mike Thomas
Could be one of the following:
A problem with the web.config of the service. For example that localhost was part of the address.
That the service cannot find the dll which should be in the bin directory
Try browsing to the service with a web browser
Try adding the port number to the computer name. Whenever I'm testing local sites through a virtual machine that is always a necessity for me.
Change this:
new EndpointAddress("http://dellnov2006/Service1.svc"));
To this:
new EndpointAddress("http://dellnov2006:1042/Service1.svc"));
The solution to this was very simple, but it took both of your answers for me to think of
it.
Browsing to the service as suggested by Shiraz worked, so problem with calling service.
Suggestion to change endpoint address to include port # sounded good, but did not work.
Solution was to change:
new EndpointAddress("http://dellnov2006/Service1.svc"));
to this:
new EndpointAddress("http://dellnov2006/Silverlight/Service1.svc"));
where 'Silverlight' is the alias of the virtual directory. In other words, I open the app on IIS as 'http://dellnov2006/Silverlight/
Many thanks, I cannot believe how simple that was after so much time spent looking. I work alone and if it were not for this forum I'd be in serious trouble.
Mike Thomas