OData used in Multi Tenant website

Feb 11, 2015 at 9:17 PM
Has anyone tried to use this on a multi tenant orchard website? I am trying to use the module on a tenant and the routes don't seem to work.
Feb 16, 2015 at 6:23 PM
I was able to get the OData module to run on one tenant, but I still have issues with routing when enabling module on multiple tenants. I modified the ODataServiceFactory to consider the URL Prefix from the shell settings of the tenant.

I added an "else if" to consider the RequestUrlPrefix.
            else if (!string.IsNullOrEmpty(shellSettings.RequestUrlPrefix))
            {
                UriBuilder ub = new UriBuilder(baseAddress);
                ub.Path = "/" + shellSettings.RequestUrlPrefix + ub.Path;
                newBaseAddresses.Add(ub.Uri);
            }
And I modified the public "CreateServiceHost" to manipulate the baseAddresses to consider the tenants.
    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
    {
        return base.CreateServiceHost(constructorString, GetBaseAddresses(baseAddresses));
    }
Here is the entire class:

using System.Collections.Generic;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Mvc;

namespace Orchard.OData
{
using Orchard.Wcf;
using System;
using System.Data.Services;
using System.ServiceModel;

internal class ODataServiceFactory : OrchardServiceHostFactory
{
    private Uri[] GetBaseAddresses(Uri[] baseAddresses)
    {
        IHttpContextAccessor accessor = HostContainer.Resolve<IHttpContextAccessor>();
        IRunningShellTable runningShellTable = HostContainer.Resolve<IRunningShellTable>();
        ShellSettings shellSettings = runningShellTable.Match(accessor.Current());

        List<Uri> newBaseAddresses = new List<Uri>();
        foreach (var baseAddress in baseAddresses)
        {
            if (!string.IsNullOrEmpty(shellSettings.RequestUrlHost))
            {
                UriBuilder ub = new UriBuilder(baseAddress);
                ub.Host = shellSettings.RequestUrlHost;
                newBaseAddresses.Add(ub.Uri);
            }
            else if (!string.IsNullOrEmpty(shellSettings.RequestUrlPrefix))
            {
                UriBuilder ub = new UriBuilder(baseAddress);
                ub.Path = "/" + shellSettings.RequestUrlPrefix + ub.Path;
                newBaseAddresses.Add(ub.Uri);
            }
            else
            {
                newBaseAddresses.Add(baseAddress);
            }
        }
        return newBaseAddresses.ToArray();
    }


    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
    {
        return base.CreateServiceHost(constructorString, GetBaseAddresses(baseAddresses));
    }

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new DataServiceHost(serviceType, baseAddresses);
    }
}
}

The remaining issue lies in routing. When I enable the OData module on a second tenant, the RouteService tries to configure the route, but an exception is thrown due to a route "~/odata" already exists. I need to figure out a way consider the tenant RequestUrlPrefix in the routing. I have modified the original to use a static property for the route. See issue https://orchardsyndication.codeplex.com/workitem/2265

Here is my current RouteProvider.cs:

using System.Web.Routing;

namespace Orchard.OData.Services
{
using Mvc.Routes;
using Orchard.WebApi.Routes;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Activation;

public class RouteService : IRouteProvider
{
    private static readonly RouteBase Route = new ServiceRoute("odata", new ODataServiceFactory(), typeof(IODataService));

    IEnumerable<RouteDescriptor> IRouteProvider.GetRoutes()
    {
        return new List<RouteDescriptor>() { 
            new RouteDescriptor {
                Priority = 9999,
                Route = Route
            }
        };
    }

    void IRouteProvider.GetRoutes(ICollection<RouteDescriptor> routes)
    {
        (this as IRouteProvider).GetRoutes().ToList().ForEach(routes.Add);
    }
}
}