Is it possible to configure a WCF service using castle windsor fluent configuration without config or svc files?
Asked Answered
O

1

6

I have an ASP .Net MVC 3.0 web application hosted on IIS and I am using Castle Windsor version 3.0.

What I would like to do is register a WCF service using the webHttpBinding without any entries in the web.config or having a .svc file. Is this possible?

I tried this in my IWindsorInstaller implementation:

container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero);

container.Register(
    Component
        .For<IMyService>()
        .ImplementedBy<MyService>()
        .AsWcfService(new DefaultServiceModel()
                          .AddBaseAddresses("http://localhost/WebApp/Services")
                          .AddEndpoints(WcfEndpoint
                                    .BoundTo(new WebHttpBinding())
                                    .At("MyService.serv"))
                          .Hosted()
                          .PublishMetadata()));

And I am ignoring anything that finishes serv like so in my RegisterRoutes method in global asax:

routes.IgnoreRoute("{resource}.serv/{*pathInfo}");

If I point a browser at http://localhost/WebApp/Services/MyService.serv I get a 404.

What am I doing wrong or am I trying to do something stupid (or not possible or both!)?

Orford answered 11/1, 2012 at 15:34 Comment(2)
That is possible only if you use special ServiceRoute to register URL routing for your service but I don't know how it works with Castle Windsor.Driven
Thanks Ladislav, that gave me a good place to start looking!Orford
O
7

Thanks to Ladislav's suggestion of using the ServiceRoute I have worked out how to do this, but I am not sure it is ideal, here is what I have done (in case Googlers find it and can improve it etc):

Created an extension method on ComponentRegistration like so:

public static ComponentRegistration<T> AddServiceRoute<T>(
    this ComponentRegistration<T> registration, 
    string routePrefix, 
    ServiceHostFactoryBase serviceHostFactory, 
    string routeName) where T : class
{
    var route = new ServiceRoute("Services/" + routePrefix + ".svc",
                                 serviceHostFactory,
                                 registration
                                     .Implementation
                                     .GetInterfaces()
                                     .Single());
    RouteTable.Routes.Add(routeName, route);           
    return registration;
}   

What that does is adds a service route that places the service under the Services folder and tacks on a .svc extension (I will probably remove that). Note, I am assuming that the service implements only one interface, but in my case that is fine and I think is good practice anyway.

I'm not sure this is the best place to have this extension method, or even if an extension method is actually needed at all - perhaps I should be doing it with a service host builder or something, I don't know!

Then in the MapRoute calls I made sure to add this to the constraints parameter as per the question MVC2 Routing with WCF ServiceRoute: Html.ActionLink rendering incorrect links!

new { controller = @"^(?!Services).*" }

This just makes anything that starts Services not get matched as a controller. I do not like this very much since I would have to add it to all of my routes - I would rather globally make the Services folder fall into the service resolver or something (I do not know enough about MVC it seems!).

Finally in my windsor installer I register the service like so:

container.AddFacility<WcfFacility>(
    f =>
        {
            f.Services.AspNetCompatibility = 
                AspNetCompatibilityRequirementsMode.Allowed;
            f.CloseTimeout = TimeSpan.Zero;
        });

container.Register(
    Component
        .For<IMyService>()
        .ImplementedBy<MyService>()
        .AsWcfService(new DefaultServiceModel()
                         .AddEndpoints(WcfEndpoint.BoundTo(new WebHttpBinding()))
                         .Hosted()
                         .PublishMetadata())
        .AddServiceRoute("MyService", new DefaultServiceHostFactory(), null));

After that I can browse to the service and it is picked up and constructed fine!

As I allude to though, it might not be the best way to do this, but it works.

Orford answered 12/1, 2012 at 8:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.