Могу ли я обрабатывать различные мультиарендные отношения с помощью глобального фильтра?

У меня есть приложение asp.net mvc, в котором реализовано членство. Таким образом, пользователь должен войти в систему. Каждый пользователь принадлежит к организации (мультитенантность).

Как бы я обработал параметр организации глобально? Я подумал, что это может быть хорошо для глобального фильтра, потому что все данные должны быть отфильтрованы для данной организации. И организация связана с именем пользователя, но не в той же таблице.

например, у меня есть действие индекса, подобное этому

public ActionResult Index()
{
var result = _repository.GetListByOrganisation(organisation);
return View(result);
}

Я думал о том, чтобы иметь глобальный атрибут, который запрашивает базу данных для организации на основе имени пользователя. Поскольку мой контроллер уже содержит атрибут авторизации, у меня есть имя пользователя. Было бы неплохо кэшировать организацию (session, controllercontext) и не запрашивать организацию из db при каждом запросе.

Это способ реализовать что-то подобное? Или есть другие способы, которые будут лучше? И как я могу установить свойство в контроллере/контексте контроллера из фильтра?

Так что любые мысли по этому поводу, а также комментарии были бы замечательными...


person server info    schedule 10.03.2011    source источник
comment
Как вы отслеживаете параметр организации на клиенте? Файл cookie, пользовательский заголовок, URL?   -  person Jon Galloway    schedule 15.03.2011


Ответы (2)


Я бы сделал это через DI.

Вы можете использовать сторонний контейнер внедрения зависимостей или собственный код. В любом случае вы хотите установить идентификатор организации на основе для каждого запроса.

Таким образом, вы будете создавать единицу работы и внедрять ее в свой контроллер. Для простоты предположим, что вашей единицей работы является поле _repository в примере кода, хотя большинство реальных приложений сложнее.

Вы добавляете параметр конструктора в контроллер:

public FooController(IFooRepository repository)
{
    this._repository = repository;
}

...и идентификатор организации на FooRepository:

public class FooRepository: IFooRepository
{
    public FooRepository(long organizationId)
    {
        this._organizationId = organizationId;
    }
}

Теперь либо в настройке контейнера DI, либо в фабрике контроллеров MVC вы все это настраиваете:

builder.Register(c => new FooRepository(GetOrgIdForCurrentUser()).As<IFooRepository>();
builder.Register(c => new FooController(c.Resolve<IFooRepository>());
person Craig Stuntz    schedule 10.03.2011
comment
Да, я уже внедряю свой репозиторий. Но у меня есть база данных хранилища пользователей и бизнес-база данных. Теперь я вошел в систему и хочу получить организацию из другой базы данных. И я подумал о том, чтобы сделать это с фильтром, так как он мне нужен почти в каждом действии контроллера... - person server info; 10.03.2011
comment
Еще раз: я бы использовал фабрику контроллеров или контейнер DI, а не фильтр, чтобы сделать это, потому что это подходящее место для внедрения конструктора. Это охватывает все контроллеры, но, в отличие от фильтра, запускается до создания контроллера. - person Craig Stuntz; 10.03.2011
comment
Я думаю, что это имеет смысл, поскольку вы уже внедряете свой репозиторий. - person Jon Galloway; 15.03.2011

Возможно, вы могли бы встроить организацию в URL-адрес, например, если ваш маршрут выглядит так: /{organization}/{controller}/{action}

то вы получите такие URL-адреса, как

  • /bigorg/продукты/список
  • /smallorg/продукты/список

и вы получите организацию в своем контроллере либо в качестве параметра вашего метода, либо через объект RouteData.

person Hector Correa    schedule 10.03.2011