Специфичные для арендатора маршруты для динамически загружаемых модулей - PullRequest
0 голосов
/ 30 августа 2011

Я использую ASP.NET MVC для разработки инфраструктуры приложений. По сути, конечная цель состоит в том, чтобы иметь возможность войти в интерфейс администратора, создать нового арендатора с пользовательскими настройками, включить нужные им модули (блог, корзина для покупок и т. Д.) ... работа выполнена - довольный клиент новым веб-сайтом. Я не использую отдельные приложения, потому что будет много общего кода, и его было бы проще поддерживать, а также потому, что было бы довольно легко подключить новый идентичный узел в пиковое время.

В зависимости от того, какие модули загружены для арендатора, для каждого арендатора применяются разные маршруты. На мой взгляд, есть три варианта:

  • Пусть все арендаторы совместно используют один и тот же набор маршрутов - однако, если имеется много модулей, он будет искать по многим маршрутам, в которых он не нуждается, и некоторые модули вполне могут иметь конфликтующие маршруты.

  • Добавьте необходимые маршруты для каждого арендатора в глобальную коллекцию маршрутов и расширьте класс маршрутов, чтобы также рассмотреть домен - но это может быстро привести к сотням маршрутов, если будет добавлено больше арендаторов.

  • Выясните, к какому арендатору обращаются в первую очередь, а затем только ищите их собственную коллекцию маршрутов - это было бы идеально, но я искал часы и совершенно не представляю, как это сделать!

Так может ли кто-нибудь указать мне правильное направление для третьего варианта или объяснить, почему один из первых двух не так уж плох?

1 Ответ

0 голосов
/ 30 августа 2011

Как каждый сайт будет отличаться в вашем приложении? Если мы предполагаем, что каждый арендатор будет идентифицирован уникальным доменным именем или именем субдомена, тогда вы можете выполнить маршрутизацию одним маршрутом и некоторыми RouteConstraints. Создайте два ограничения, одно для контроллеров, другое для действий. Предполагая, что в вашей базе данных будут таблицы, в которых перечислены доступные контроллеры / действия для конкретного арендатора, ваши ограничения будут следующими:

using System; 
using System.Web; 
using System.Web.Routing;  

namespace ExampleApp.Extensions 
{ 
    public class IsControllerValidForTenant : IRouteConstraint
    {
        public IsControllerValidForTenant() { }

        private DbEntities _db = new DbEntities();

        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            // determine domain
            var domainName = httpContext.Request.Url.DnsSafeHost;
            var siteId = _db.Sites.FirstorDefault(s => s.DomainName == domainName).SiteId;
            // passed constraint if this controller is valid for this tenant
            return (_db.SiteControllers.Where(sc => sc.Controller == values[parameterName].ToString() && sc.SiteId == siteId).Count() > 0);
        }
    }

    public class IsActionValidForTenant : IRouteConstraint
    {
        public IsActionValidForTenant() { }

        private DbEntities _db = new DbEntities();

        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            // determine domain
            var domainName = httpContext.Request.Url.DnsSafeHost;
            var siteId = _db.Sites.FirstorDefault(s => s.DomainName == domainName).SiteId;
            // passed constraint if this action is valid for this tenant
            return (_db.SiteActions.Where(sa => sa.Action == values[parameterName].ToString() && sa.SiteId == siteId).Count() > 0);
        }
    }
}

Затем в Global.asax.cs определите ваш маршрут следующим образом:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
        new { controller = new IsControllerValidForTenant(), action = new IsActionValidForTenant(),}
    );
}

Когда поступает запрос, ограничения проверяют, являются ли контроллер и действие действительными для домена, так что только действительные контроллеры и действия для этого арендатора будут проходить RouteConstraints.

...