asp.mvc 404 Ошибка с Custom ControllerFactory и DBProvider - PullRequest
2 голосов
/ 03 января 2011

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

Нам нужно следующее поведение:

1) если для запроса существует «физическое» представление, обслуживайте его непосредственно из файловой системы (следуйте стандартному поведению mvc). В этом случае на диске будет стандартный контроллер / просмотр. 2) если контроллер / представление не существует, проверьте, хранится ли необходимая информация в базе данных, и отправьте ее из базы данных. Будет вызван контроллер GenericController, который, в свою очередь, получит данные представления из базы данных.

Я создал фабрику пользовательских контроллеров:

 public class ControllerFactory : DefaultControllerFactory, IControllerFactory
{
    protected override Type GetControllerType(RequestContext requestContext, string controllerName)
    {
        // check to see if this controller name can be resolved via DI.  If it can, then hand this off to the Default factory.
        Type returntype = base.GetControllerType(requestContext, controllerName);

        // see if this is a type that is handled via the database.  If it is, then send to the generic system controller for handling.
        if (returntype == null)
        {
            // already requested?
            if (requestContext.HttpContext.Items.Contains("vc"))
            {
                returntype = typeof(GenericSystemController);
            }
            else
            {

                    if (viewcanberetrievedfromdb())
                    {
                        // TODO: check to see if the account has access to the module.
                        returntype = typeof(GenericSystemController);
                        requestContext.HttpContext.Items["vc"] = viewcontext;
                    }

            }
        }

        return returntype;
    }

А также пользовательский поставщик виртуальных путей:

  public class DbPathProvider : VirtualPathProvider
{
    public DbPathProvider()
        : base()
    {

    }

    public override bool FileExists(string virtualPath)
    {
        // first see if there is a physical version of the file.  If there is, then use that.  Otherwise, go to the database.
        // database calls are ALWAYS overridden by physical files.
        bool physicalFileExists = base.FileExists(virtualPath);

        if (!physicalFileExists)
            physicalFileExists = HttpContext.Current.Items.Contains("vc");


        return physicalFileExists;
    }

    public override VirtualFile GetFile(string virtualPath)
    {
        if (base.FileExists(virtualPath))
            return base.GetFile(virtualPath);
        else
            return new DbVirtualFile(virtualPath);
    }

Поток приложения работает правильно, если запрашивается страница, которая не существует в файловой системе: 1) первый вызов FileExists в virtualpathprovider возвращает false, поэтому IIS не пытается служить статическим файлом. 2) метод GetControllerType в фабрике контроллеров вызывается, и он соответствующим образом возвращает мой тип genericcontroller. 3) метод FileExists вызывается снова и на этот раз возвращает true. 4) Вызываются все методы фабрики контроллеров, включая метод ControllerRelease.

Однако GenericController фактически никогда не вызывается. И IIS возвращает исключение 404.

Есть ли где-то еще в конвейере создания экземпляра контроллера MVC, что мне нужно для захвата запроса MVC? Есть ли лучший способ для меня выполнить то, что я пытаюсь сделать?

Спасибо.

...