/// <summary>
        /// Creates a <see cref="PageApplicationModel"/> for the given <paramref name="pageTypeInfo"/>.
        /// </summary>
        /// <param name="actionDescriptor">The <see cref="PageActionDescriptor"/>.</param>
        /// <param name="pageTypeInfo">The <see cref="TypeInfo"/>.</param>
        /// <returns>A <see cref="PageApplicationModel"/> for the given <see cref="TypeInfo"/>.</returns>
        protected virtual PageApplicationModel CreateModel(
            PageActionDescriptor actionDescriptor,
            TypeInfo pageTypeInfo)
        {
            if (actionDescriptor == null)
            {
                throw new ArgumentNullException(nameof(actionDescriptor));
            }

            if (pageTypeInfo == null)
            {
                throw new ArgumentNullException(nameof(pageTypeInfo));
            }

            if (!typeof(PageBase).GetTypeInfo().IsAssignableFrom(pageTypeInfo))
            {
                throw new InvalidOperationException(Resources.FormatInvalidPageType_WrongBase(
                                                        pageTypeInfo.FullName,
                                                        typeof(PageBase).FullName));
            }

            // Pages always have a model type. If it's not set explicitly by the developer using
            // @model, it will be the same as the page type.
            var modelProperty = pageTypeInfo.GetProperty(ModelPropertyName, BindingFlags.Public | BindingFlags.Instance);

            if (modelProperty == null)
            {
                throw new InvalidOperationException(Resources.FormatInvalidPageType_NoModelProperty(
                                                        pageTypeInfo.FullName,
                                                        ModelPropertyName));
            }

            var modelTypeInfo     = modelProperty.PropertyType.GetTypeInfo();
            var declaredModelType = modelTypeInfo;

            // Now we want figure out which type is the handler type.
            TypeInfo handlerType;

            if (modelProperty.PropertyType.IsDefined(typeof(PageModelAttribute), inherit: true))
            {
                handlerType = modelTypeInfo;
            }
            else
            {
                handlerType = pageTypeInfo;
            }

            var handlerTypeAttributes = handlerType.GetCustomAttributes(inherit: true);
            var pageModel             = new PageApplicationModel(
                actionDescriptor,
                declaredModelType,
                handlerType,
                handlerTypeAttributes)
            {
                PageType  = pageTypeInfo,
                ModelType = modelTypeInfo,
            };

            PopulateHandlerMethods(pageModel);
            PopulateHandlerProperties(pageModel);
            PopulateFilters(pageModel);

            return(pageModel);
        }
    /// <summary>
    /// Creates a <see cref="PageApplicationModel"/> for the given <paramref name="pageTypeInfo"/>.
    /// </summary>
    /// <param name="actionDescriptor">The <see cref="PageActionDescriptor"/>.</param>
    /// <param name="pageTypeInfo">The <see cref="TypeInfo"/>.</param>
    /// <returns>A <see cref="PageApplicationModel"/> for the given <see cref="TypeInfo"/>.</returns>
    private PageApplicationModel CreateModel(
        PageActionDescriptor actionDescriptor,
        TypeInfo pageTypeInfo)
    {
        if (actionDescriptor == null)
        {
            throw new ArgumentNullException(nameof(actionDescriptor));
        }

        if (pageTypeInfo == null)
        {
            throw new ArgumentNullException(nameof(pageTypeInfo));
        }

        if (!typeof(PageBase).GetTypeInfo().IsAssignableFrom(pageTypeInfo))
        {
            throw new InvalidOperationException(Resources.FormatInvalidPageType_WrongBase(
                                                    pageTypeInfo.FullName,
                                                    typeof(PageBase).FullName));
        }

        // Pages always have a model type. If it's not set explicitly by the developer using
        // @model, it will be the same as the page type.
        var modelProperty = pageTypeInfo.GetProperty(ModelPropertyName, BindingFlags.Public | BindingFlags.Instance);

        if (modelProperty == null)
        {
            throw new InvalidOperationException(Resources.FormatInvalidPageType_NoModelProperty(
                                                    pageTypeInfo.FullName,
                                                    ModelPropertyName));
        }

        var modelTypeInfo     = modelProperty.PropertyType.GetTypeInfo();
        var declaredModelType = modelTypeInfo;

        // Now we want figure out which type is the handler type.
        TypeInfo handlerType;
        var      pageTypeAttributes = pageTypeInfo.GetCustomAttributes(inherit: true);

        object[] handlerTypeAttributes;
        if (modelProperty.PropertyType.IsDefined(typeof(PageModelAttribute), inherit: true))
        {
            handlerType = modelTypeInfo;

            // If a PageModel is specified, combine the attributes specified on the Page and the Model type.
            // Attributes that appear earlier in the are more significant. In this case, we'll treat attributes on the model (code)
            // to be more signficant than the page (code-generated).
            handlerTypeAttributes = modelTypeInfo.GetCustomAttributes(inherit: true).Concat(pageTypeAttributes).ToArray();
        }
        else
        {
            handlerType           = pageTypeInfo;
            handlerTypeAttributes = pageTypeInfo.GetCustomAttributes(inherit: true);
        }

        var pageModel = new PageApplicationModel(
            actionDescriptor,
            declaredModelType,
            handlerType,
            handlerTypeAttributes)
        {
            PageType  = pageTypeInfo,
            ModelType = modelTypeInfo,
        };

        PopulateHandlerMethods(pageModel);
        PopulateHandlerProperties(pageModel);
        PopulateFilters(pageModel);

        return(pageModel);
    }