Creating Module with WCF Service

Topics: Troubleshooting
Nov 1, 2011 at 2:47 PM

Hi,

I'm hoping someone can help me with getting a WCF service to run within a module. I have looked for help on this and found various semi-solutions, but nothing has got me up and running yet. No matter what I do, I get a 404 when trying to access my service.

I've looked at these articles:

http://stackoverflow.com/questions/5795632/orchard-mvc-wcf-service-url-with-area

http://stackoverflow.com/questions/3186858/can-a-wcf-serviceroute-route-prefix-contain-a-path-value

http://orchard.codeplex.com/discussions/262524

Here's my current setup:

Web.config

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
        <behavior name="">
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>
</system.serviceModel>

Routes.cs

 public class Routes : IRouteProvider

{
    public void GetRoutes(ICollection<RouteDescriptor> routes)
    {
        foreach (var routeDescriptor in GetRoutes())
        {
            routes.Add(routeDescriptor);
        }
    }

    public IEnumerable<RouteDescriptor> GetRoutes()
    {
        return new[] 
        {
            new RouteDescriptor
            {
                Priority = 20,
                Route = new ServiceRoute("ProfileService", new OrchardServiceHostFactory(), typeof(IStaffProfileService))
            }
        };
    }
}

IStaffProfileService.cs

[ServiceContract]
public interface IStaffProfileService : IDependency
{
    [OperationContract]
    string TestMethod();
}


I'm trying to get at it via: http://localhost/ProfileService although I've tried many variations of routes and urls. Can anyone see what I'm missing here?

Many Thanks!


Nov 2, 2011 at 2:23 PM

I think this might be a bug. At any rate, I can't figure out why the Orchard route is not hitting my service. Eventually, I got it to work like this (which is hacky):

public class Routes : IRouteProvider
{
    public void GetRoutes(ICollection<RouteDescriptor> routes)
    {
        foreach (var routeDescriptor in GetRoutes())
        {
            routes.Add(routeDescriptor);
        }
    }

    public IEnumerable<RouteDescriptor> GetRoutes()
    {
        RouteTable.Routes.Add(new ServiceRoute("ProfileService", new OrchardServiceHostFactory(), typeof(IStaffProfileService)));

        return new RouteDescriptor[0];
    }
}
Instead of:

public class Routes : IRouteProvider
{
    public void GetRoutes(ICollection<RouteDescriptor> routes)
    {
        foreach (var routeDescriptor in GetRoutes())
        {
            routes.Add(routeDescriptor);
        }
    }

    public IEnumerable<RouteDescriptor> GetRoutes()
    {
        return new[]
            {
                new RouteDescriptor
                {
                    Priority = 10,
                    Route = new ServiceRoute("ProfileService", new OrchardServiceHostFactory(), typeof(IStaffProfileService))
                }
            };
    }
}

Anyway, I haven't reported it as an issue because I could just be going crazy. I'll be using my workaround for now.

Cheers.

Nov 2, 2011 at 2:53 PM

A little more info, for anyone who may be reading this...

In Orchard.Mvc.Routes.RoutePublisher there is a method Publish(IEnumerable<RouteDescriptor> routes)

if you change:

var routesArray = routes
    .OrderByDescending(r => r.Route is ServiceRoute ? -1 : 1)
    .ThenByDescending(r => r.Priority)
    .ToArray();
to

var routesArray = routes
    /*.OrderByDescending(r => r.Route is ServiceRoute ? 1 : -1)*/
    .OrderByDescending(r => r.Priority)
    .ToArray();

the service routing then works. Could it be that because the ServiceRoute is being put right at the very end, a route further up is matching first and then for some reason 404'ing? I don't pretend to know enough about the inner workings of routing/mvc/orchard to know whether this is a bug or whether I'm doin it wrong, just trying to be helpful!

Cheers!

Dec 6, 2011 at 12:46 PM

I've used this same technique and my service work and is accessible by the client.  However, I don't have access to any of the Orchard services registered in Autofac.  I've implemented IShim in my service and have a HostContainer injected into the service but I don't seem to be able to resolved any interfaces.

    public class CNService : ICNService, Orchard.Environment.IShim

    {
        private IOrchardHostContainer hostContainer = null;

        public CNService()
        { 
            OrchardHostContainerRegistry.RegisterShim(this);
            IRunningShellTable runningShellTable = HostContainer.Resolve<IRunningShellTable>();
            HttpContextWrapper contextWrapper = new HttpContextWrapper(HttpContext.Current);
            ShellSettings shellSettings = runningShellTable.Match(contextWrapper);
            IOrchardHost orchardHost = HostContainer.Resolve<IOrchardHost>();

            ShellContext shellContext = orchardHost.GetShellContext(shellSettings);
            IWorkContextAccessor workContextAccessor = shellContext.LifetimeScope.Resolve<IWorkContextAccessor>();
            WorkContext workContext = workContextAccessor.GetContext();


            ILifetimeScope lifetimeScope = workContext.Resolve<ILifetimeScope>();

            // Generates Exception
            ILogger logger = workContext.Resolve<ILogger>();

        }

Can someone point me in the right direction?