Configuring a WCF and StructureMap ServiceHostFactory from code - wcf

I am creating a custom ServiceHost object and configuring it from code. My service is using InstanceContextMode.Single and ConcurrencyMode.Multiple and is hosted in a windows service.
As stated in a number of blogs/articles (here), sharing a StructureMap container across instances requires using a custom InstanceProvider, ServiceBehavior and ServiceHostFactory.
My initialization code looks like this. I do not use a config file.
var baseAddress = ConfigurationManager.AppSettings["BaseAddress"];
var port = Int32.Parse(ConfigurationManager.AppSettings["Port"]);
Host = new MyServiceHost(typeof(MediaFileServicePrivate), new Uri(string.Format(baseAddress, port)));
var binding = new NetTcpBinding();
Host.AddServiceEndpoint(typeof(IMediaFileServicePrivate), binding, string.Format(baseAddress, port));
How do I tell the service to use my custom service host factory? All the examples I can find configure it from the config file.
Is a ServiceHostFactory only used for IIS/WAS hosted scenarios? If so, how do I use SM for a self-hosted InstanceContextMode.Single service?

Has this not been answered? essentially you tell it to use your servicefactory in the wcf markup
<%# ServiceHost Language="C#" Debug="true" Service="WcfWithDI.Service1" CodeBehind="Service1.svc.cs" Factory="WcfWithDI.MyServiceFactory"%>
I have a sample project here all wired up with a custom provider (and structuremap)
https://github.com/billCreativeD/WCF_With_DI

Unfortunately it makes little sense to say "the service uses the factory". You would use the Ninject factory to create your service:
var factory = new NinjectServiceHostFactory();
var address = new Uri(_baseAddress, path);
ServiceHostBase host = factory.CreateServiceHost(typeName, new[] {address});
var binding = new NetTcpBinding();
host.AddServiceEndpoint(typeof(TheType), binding, string.Format(baseAddress, port));
The directive in the .svc file is used to tell .NET how to instantiate your service.

Related

WCF: how to restrict using some protocols?

WCF (winodws service hosting) service uses set of protocols and bindings: http, https, net.tcp, net.pipe.
It uses config file settings.
I want to build demo version of the service.
This demo will use only net.pipe protocol.
How I can restrict service to use only this one?
I can do changes in code , but how and where?
ServiceHost owns collection of ChannelDispatchers in ChannelDispatchers property. You can use ChannelDispatcher.BindingName to figure out name of binding used in your service.
ServiceHost host = new ServiceHost(typeof(SomeService), baseAddress))
//configure service endpoints here
host.Open();
#if DEMO_MODE
foreach (ChannelDispatcher dispatcher in host.ChannelDispatchers)
{
//binding name includes namespace. Example - http://tempuri.org/:NetNamedPipeBinding
var bindingName = dispatcher.BindingName;
if (!(bindingName.EndsWith("NetNamedPipeBinding") || bindingName.EndsWith("MetadataExchangeHttpBinding")))
throw new ApplicationException("Only netNamedPipeBinding is supported in demo mode");
}
#endif

Autofac WCF integration + sessions

I am having an ASP.NET MVC 3 application that collaborates with a WCF service, which is hosted using Autofac host factory. Here are some code samples:
.svc file:
<%# ServiceHost
Language="C#"
Debug="true"
Service="MyNamespace.IMyContract, MyAssembly"
Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf" %>
Global.asax of the WCF service project:
protected void Application_Start(object sender, EventArgs e)
{
ContainerBuilder builder = new ContainerBuilder();
//Here I perform all registrations, including implementation of IMyContract
AutofacServiceHostFactory.Container = builder.Build();
}
Client proxy class constructor (MVC side):
ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new ChannelFactory<IMyContract>(
new BasicHttpBinding(),
new EndpointAddress(Settings.Default.Url_MyService)))
.SingleInstance();
builder.Register(c => c.Resolve<ChannelFactory<IMyContract>>().CreateChannel())
.UseWcfSafeRelease();
_container = builder.Build();
This works fine until I want WCF service to allow or require sessions ([ServiceContract(SessionMode = SessionMode.Allowed)], or [ServiceContract(SessionMode = SessionMode.Required)]) and to share one session with the MVC side. I changed the binding to WSHttpBinding on the MVC side, but I am having different exceptions depending on how I tune it.
I also tried changing AutofacServiceHostFactory to AutofacWebServiceHostFactory, with no result.
I am not using config file as I am mainly experimenting, not developing real-life application, but I need to study the case. But if you think I can achieve what I need only with config files, then OK, I'll use them.
I will provide exception details for each combination of settings if required, I'm omitting them not to make the post too large. Any ideas on what I can do?

how to host custom wcf applicaion(server) on IIS7.5?

I've used custom wcf applicaion as wcf server by using:
ServiceHost<AlertService> alertServiceHost = new ServiceHost<AlertService>();
configuredEndpoints = alertServiceHost.Description.Endpoints;
alertServiceHost.Open();
Now, I have a problem with deployment on production which is IIS7.5.
I have no idea how to deploy on IIS. Because I only know that I have to create svc file for hosting on IIS. Now, I only have console application working as wcf service.
How can I transform it to deploy on IIS?
Thank you.
If you want to use a custom service host in a IIS hosting scenario, you need to supply a custom ServiceHostFactory that will return that type of service host, and configure that service host factory in your SVC file.
Basically, your custom service host factory must descend from ServiceHostFactory and override one method that returns an instance of your custom service host - something along the lines of:
public class MyOwnServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type t, Uri[] baseAddresses)
{
return new MyOwnCustomServiceHost(t, baseAddresses);
}
public override ServiceHostBase CreateServiceHost(string service, Uri[] baseAddresses)
{
// The service parameter is ignored here because we know our service.
ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddresses);
return serviceHost;
}
}
And in your SVC file, you now need to have:
<%# ServiceHost Language="C#" Debug="true"
Service="YourNamespace.YourService"
Factory="YourNamespace.MyOwnServiceHostFactory" %>
Read more about:
ServiceHostFactory on MSDN
Extending hosting using ServiceHostFactory
When hosting in IIS you don't create ServiceHost by yourselves. It is reponsibility of IIS and reason why .svc file exists. Svc file instructs worker process how and which service should be hosted.
Svc file consists of simple directive (markup):
<%# ServiceHost Language="C#" Debug="true" Service="MyNamespace.MyService" CodeBehind="MyService.svc.cs" %>
This is example of .svc file hosting locally create service but you can omit CodeBehind attribute and use full type description in Service attribute to host service class from another assembly.
Also check How to: Host WCF service in IIS.

How do I supply a specific instance of a class, to expose as my WCF service

I have a class that implements a plugin for an existing application.
I also have exposed that class as a WCF service. That part is working so far. The problem I am running into is that the application I am plugging into creates the instance of my class that I want to use.
Is there a way to pass an existing class instance to the WCF service host, to expose as a service endpoint?
I know (or can figure out) how to make a singleton instance of a WCF service, but that still won't help me. From what I can tell, the singleton instance will still be created and provided by WCF.
I have thought of other approaches, but I'd rather take this one if it is available to me.
Some code. This is in the constructor of my plugin:
// Setup the service host
var baseAddress = new Uri("http://localhost:8080/MyService/");
this.serviceHost = new ServiceHost(this.GetType(), baseAddress);
// Add our service endpoint
// Todo: Is there somewhere around here that I can provide an instance?
// Maybe in behavior somewhere?
this.serviceHost.AddServiceEndpoint(
typeof(ITheInterfaceMyClassDerivesFrom),
new BasicHttpBinding(),
""
);
// Add metadata exchange (so we see something when we go to that URL)
var serviceMetadataBehavior = this.serviceHost.Description.Behaviors
.Find<ServiceMetadataBehavior>();
if (serviceMetadataBehavior == null)
this.serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior());
this.serviceHost.AddServiceEndpoint(
typeof(IMetadataExchange),
new CustomBinding(new HttpTransportBindingElement()),
"MEX"
);
This is in the plugin's OnStartedUp method (called by the application I am plugging into):
serviceHost.Open();
You need to use the other constructor for ServiceHost if you want to do this - check out the MSDN docs at http://msdn.microsoft.com/en-us/library/ms585487.aspx
public ServiceHost(
Object singletonInstance,
params Uri[] baseAddresses
)

Problem creating WCF service with Windsor

Does anyone know how to configure WCF using Windsor on IIS 7.0? I'm using the latest from WCF Windsor facility trunk and Windsor 2.1.1. The example on http://www.castleproject.org/container/facilities/trunk/wcf/index.html is out of date. Even demo project in WCF facility doesn't mention how to setup WCF service in IIS using the config and I couldn't find any example where I can setup WCF on server side using system.serviceModel section of web.config or even through code. When I use the following code it always creates basicHttpBinding and I couldn't figure out how to setup different bindings.
protected void Application_Start(object sender, EventArgs e)
{
var returnFaults = new ServiceDebugBehavior
{
IncludeExceptionDetailInFaults = true,
HttpHelpPageEnabled = true
};
var metadata = new ServiceMetadataBehavior {HttpGetEnabled = true};
container = new WindsorContainer()
.AddFacility<WcfFacility>()
.Register(
Component.For<IServiceBehavior>().Instance(returnFaults),
Component.For<IServiceBehavior>().Instance(metadata),
Component.For<IMyService>()
.Named("MyService")
.ImplementedBy<MyService>()
.LifeStyle.Transient
);
}
And here is MyService.svc
<%# ServiceHost Language="C#" Debug="true" Service="MyService"
Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" %>
I recently wrote a blog post about Windsor's WCF Facility. Be sure to read the comments as well, as they include a discussion involving one of Windsor's active committers; they should give you a pretty good impression of the future direction.