예제 #1
0
        private void handleEndRequest(object sender, EventArgs e)
        {
            if (!FrameworkInitialized || RequestState == null)
            {
                return;
            }

            // Do not set a status code since we may have already set one or set a redirect page.
            ExecuteWithBasicExceptionHandling(() => RequestState.CleanUp(), false, false);
            RequestState = null;
        }
예제 #2
0
        private void handleBeginRequest(object sender, EventArgs e)
        {
            if (!FrameworkInitialized)
            {
                // We can't redirect to a normal page to communicate this information because since initialization failed, the request for that page will trigger
                // another BeginRequest event that puts us in an infinite loop. We can't rely on anything except an HTTP return code. Suppress exceptions; there is no
                // way to report them since even our basic exception handling may not work if the application isn't initialized.
                try {
                    set500StatusCode("Initialization Failure");
                }
                catch {}
                return;
            }

            ExecuteWithBasicExceptionHandling(
                delegate {
                if (RequestState != null)
                {
                    RequestState = null;
                    throw new ApplicationException("AppRequestState was not properly cleaned up from a previous request.");
                }


                // This used to be just HttpContext.Current.Request.Url, but that doesn't work with Azure due to the use of load balancing. An Azure load balancer
                // will bind to the ip/host/port through which all web requests should come in, and then the request is redirected to one of the server instances
                // running this web application. For example, a user will request mydomain.com. In Azure, there may be two instances running this web site, on
                // someIp:81 and someIp:82. For some reason, HttpContext.Current.Request.Url ends up using the host and port from one of these addresses instead of
                // using the host and port from the HTTP Host header, which is what the client is actually "viewing". Basically, HttpContext.Current.Request.Url
                // returns http://someIp:81?something=1 instead of http://mydomain.com?something=1. See
                // http://stackoverflow.com/questions/9560838/azure-load-balancer-causes-400-error-invalid-hostname-on-postback.

                var baseUrl = getRequestBaseUrl(Request);
                if (!baseUrl.Any())
                {
                    setStatusCode(400);
                    return;
                }
                var appRelativeUrl = GetRequestAppRelativeUrl(Request, disableLeadingSlashRemoval: true);

                // If the base URL doesn't include a path and the app-relative URL is just a slash, don't include this trailing slash in the URL since it will not be
                // present in the canonical URLs that we construct and therefore it would cause problems with URL normalization.
                var url = !getRequestBasePath(Request).Any() && appRelativeUrl.Length == "/".Length ? baseUrl : baseUrl + appRelativeUrl;


                // This blocks until the entire request has been received from the client.
                // This won't compile unless it is assigned to something, which is why it is unused.
                var stream = Request.InputStream;

                RequestState = new AppRequestState(url);
            },
                false,
                true);
        }
예제 #3
0
        private void handleEndRequest(object sender, EventArgs e)
        {
            if (!FrameworkInitialized || RequestState == null)
            {
                return;
            }

            ExecuteWithBasicExceptionHandling(
                delegate {
                try {
                    // This 404 condition covers two types of requests:
                    // 1. Requests where we set the status code in handleError
                    // 2. Requests to handlers that set the status code directly instead of throwing exceptions, e.g. the IIS static file handler
                    if (Response.StatusCode == 404 && !handleErrorIfOnErrorPage("A status code of 404 was produced", null))
                    {
                        transferRequest(getErrorPage(MetaLogicFactory.CreatePageNotAvailableErrorPageInfo(!RequestState.HomeUrlRequest)), false);
                    }

                    if (RequestState.TransferRequestPath.Length > 0)
                    {
                        // NOTE: If we transfer to a path with no query string, TransferRequest adds the current query string. Because of this bug we need to make sure all
                        // pages we transfer to have at least one parameter.
                        Server.TransferRequest(RequestState.TransferRequestPath, false, "GET", null);
                    }
                }
                catch {
                    RequestState.RollbackDatabaseTransactions();
                    DataAccessState.Current.ResetCache();
                    throw;
                }
            },
                true,
                true);

            // Do not set a status code since we may have already set one or set a redirect page.
            ExecuteWithBasicExceptionHandling(delegate { RequestState.CleanUp(); }, false, false);
            RequestState = null;
        }
        /// <summary>
        /// Call this from Application_Start in your Global.asax.cs file. Besides this call, there should be no other code in the method.
        /// </summary>
        /// <param name="globalInitializer">The system's global initializer. Do not pass null.</param>
        /// <param name="appInitializer">The application initializer, which performs web-site specific initialization and cleanup. If you have one of these you
        /// should name the class AppInitializer.</param>
        public static void InitStatics(SystemInitializer globalInitializer, SystemInitializer appInitializer = null)
        {
            // This is a hack to support data-access state in WCF services.
            var wcfDataAccessState = new ThreadLocal <DataAccessState>(() => new DataAccessState());

            // Initialize system.
            var initTimeDataAccessState = new ThreadLocal <DataAccessState>(() => new DataAccessState());

            try {
                GlobalInitializationOps.InitStatics(
                    globalInitializer,
                    Path.GetFileName(Path.GetDirectoryName(HttpRuntime.AppDomainAppPath)),
                    false,
                    mainDataAccessStateGetter: () => {
                    return(EwfApp.Instance != null ? EwfApp.Instance.RequestState != null ? EwfApp.Instance.RequestState.DataAccessState :
                           initTimeDataAccessState.Value :
                           System.ServiceModel.OperationContext.Current != null ? wcfDataAccessState.Value : null);
                });
            }
            catch {
                // Suppress all exceptions since there is no way to report them.
                return;
            }
            ewlInitialized = true;

            // Initialize web application.
            if (!GlobalInitializationOps.SecondaryInitFailed)
            {
                EwfApp.ExecuteWithBasicExceptionHandling(
                    () => {
                    EwfConfigurationStatics.Init();

                    GlobalConfiguration.Configure(WebApiStatics.ConfigureWebApi);

                    var miniProfilerOptions = new MiniProfilerOptions();
                    miniProfilerOptions.IgnoredPaths.Clear();
                    MiniProfiler.Configure(miniProfilerOptions);

                    var globalType     = BuildManager.GetGlobalAsaxType().BaseType;
                    var providerGetter = new SystemProviderGetter(
                        globalType.Assembly,
                        globalType.Namespace + ".Providers",
                        providerName =>
                        @"{0} provider not found in application. To implement, create a class named {0} in ""Your Web Site\Providers"" that derives from App{0}Provider."
                        .FormatWith(providerName));

                    if (ExternalFunctionalityStatics.SamlFunctionalityEnabled)
                    {
                        ExternalFunctionalityStatics.ExternalSamlProvider.InitAppStatics(
                            providerGetter,
                            () => AuthenticationStatics.SamlIdentityProviders.Select(
                                identityProvider => {
                            using (var client = new HttpClient()) {
                                client.Timeout = new TimeSpan(0, 0, 10);
                                var metadata   = Task.Run(
                                    async() => {
                                    using (var response = await client.GetAsync(identityProvider.MetadataUrl, HttpCompletionOption.ResponseHeadersRead)) {
                                        response.EnsureSuccessStatusCode();
                                        var document = new XmlDocument();
                                        using (var stream = await response.Content.ReadAsStreamAsync())
                                            using (var reader = XmlReader.Create(stream))
                                                document.Load(reader);
                                        return(document.DocumentElement);
                                    }
                                })
                                                 .Result;
                                return(metadata, identityProvider.EntityId);
                            }
                        })
                            .Materialize());
                    }

                    UrlHandlingStatics.Init(
                        (baseUrlString, appRelativeUrl) =>
                        AppRequestState.ExecuteWithUrlHandlerStateDisabled(() => UrlHandlingStatics.ResolveUrl(baseUrlString, appRelativeUrl)?.Last()));
                    CssPreprocessingStatics.Init(globalInitializer.GetType().Assembly, globalType.Assembly);
                    ResourceBase.Init(
                        (requestTransferred, resource) => {
                        if (requestTransferred)
                        {
                            var urlHandlers       = new List <BasicUrlHandler>();
                            UrlHandler urlHandler = resource;
                            do
                            {
                                urlHandlers.Add(urlHandler);
                            }while((urlHandler = urlHandler.GetParent()) != null);
                            AppRequestState.Instance.SetUrlHandlers(urlHandlers);

                            AppRequestState.Instance.SetNewUrlParameterValuesEffective(false);
                            AppRequestState.Instance.SetResource(resource);
                        }
                        else
                        {
                            AppRequestState.Instance.SetResource(resource);
                        }
                    },
                        () => AppRequestState.Instance.Resource);
                    PageBase.Init(
                        (() => BasePageStatics.AppProvider.GetPageViewDataModificationMethod(), () => BasePageStatics.AppProvider.JavaScriptDocumentReadyFunctionCall),
                        BasicPageContent.GetContent);
                    HyperlinkBehaviorExtensionCreators.Init(ModalBox.GetBrowsingModalBoxOpenStatements);
                    FileUpload.Init(() => ((BasicPageContent)PageBase.Current.BasicContent).FormUsesMultipartEncoding = true);
                    ModalBox.Init(() => ((BasicPageContent)PageBase.Current.BasicContent).BrowsingModalBoxId);
                    CreditCardCollector.Init(() => ((BasicPageContent)PageBase.Current.BasicContent).IncludesStripeCheckout = true);
                    BasePageStatics.Init(providerGetter.GetProvider <AppStandardPageLogicProvider>("StandardPageLogic"));
                    BasicPageContent.Init(
                        contentObjects => {
                        var contentUsesUi = contentObjects.Any(i => i is UiPageContent);

                        var cssInfos = new List <ResourceInfo>();
                        cssInfos.Add(
                            new ExternalResource(
                                "//fonts.googleapis.com/css2?family=Libre+Franklin:wght@500;600;700&family=Open+Sans:ital,wght@0,400;0,600;0,700;1,400&display=fallback"));
                        cssInfos.Add(new ExternalResource("//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"));
                        cssInfos.Add(new StaticFiles.Versioned.Third_party.Jquery_ui.Jquery_ui_1114custom_v2.Jquery_uiminCss());
                        cssInfos.Add(new StaticFiles.Third_party.Select_cssCss());
                        cssInfos.Add(new StaticFiles.Versioned.Third_party.Chosen.Chosen_v187.ChosenminCss());
                        cssInfos.Add(new StaticFiles.Third_party.Time_picker.StylesCss());
                        cssInfos.Add(new ExternalResource("//cdn.jsdelivr.net/qtip2/2.2.1/jquery.qtip.min.css"));
                        cssInfos.Add(new ExternalResource("//cdnjs.cloudflare.com/ajax/libs/dialog-polyfill/0.4.9/dialog-polyfill.min.css"));
                        cssInfos.Add(new StaticFiles.Styles.BasicCss());
                        if (contentUsesUi)
                        {
                            cssInfos.AddRange(
                                new ResourceInfo[]
                            {
                                new StaticFiles.Styles.Ui.ColorsCss(), new StaticFiles.Styles.Ui.FontsCss(), new StaticFiles.Styles.Ui.LayoutCss(),
                                new StaticFiles.Styles.Ui.TransitionsCss()
                            });
                        }
                        foreach (var resource in BasePageStatics.AppProvider.GetStyleSheets())
                        {
                            assertResourceIsIntermediateInstallationPublicResourceWhenNecessary(resource);
                            cssInfos.Add(resource);
                        }
                        if (contentUsesUi)
                        {
                            foreach (var resource in EwfUiStatics.AppProvider.GetStyleSheets())
                            {
                                assertResourceIsIntermediateInstallationPublicResourceWhenNecessary(resource);
                                cssInfos.Add(resource);
                            }
                        }
                        else
                        {
                            foreach (var resource in BasePageStatics.AppProvider.GetCustomUiStyleSheets())
                            {
                                assertResourceIsIntermediateInstallationPublicResourceWhenNecessary(resource);
                                cssInfos.Add(resource);
                            }
                        }
                        return(cssInfos);
                    },
                        (markup, includeStripeCheckout) => {
                        string getElement(ResourceInfo resource) => "<script src=\"{0}\" defer></script>".FormatWith(resource.GetUrl());

                        var infos = new List <ResourceInfo>();
                        infos.Add(new ExternalResource("//code.jquery.com/jquery-1.12.3.min.js"));
                        infos.Add(new StaticFiles.Versioned.Third_party.Jquery_ui.Jquery_ui_1114custom_v2.Jquery_uiminJs());
                        infos.Add(new StaticFiles.Versioned.Third_party.Chosen.Chosen_v187.ChosenjqueryminJs());
                        infos.Add(new StaticFiles.Third_party.Time_picker.CodeJs());
                        infos.Add(new ExternalResource("//cdn.jsdelivr.net/qtip2/2.2.1/jquery.qtip.min.js"));
                        infos.Add(new ExternalResource("//cdnjs.cloudflare.com/ajax/libs/dialog-polyfill/0.4.9/dialog-polyfill.min.js"));
                        infos.Add(new StaticFiles.Third_party.Spin_js.SpinminJs());
                        infos.Add(new ExternalResource("//cdn.ckeditor.com/4.5.8/full/ckeditor.js"));
                        infos.Add(new ExternalResource("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"));
                        infos.Add(new ExternalResource("https://instant.page/5.1.0"));
                        if (includeStripeCheckout)
                        {
                            infos.Add(new ExternalResource("https://checkout.stripe.com/checkout.js"));
                        }
                        infos.Add(new StaticFiles.CodeJs());
                        foreach (var i in infos.Select(getElement))
                        {
                            markup.Append(i);
                        }
                        markup.Append(MiniProfiler.Current.RenderIncludes().ToHtmlString());
                        foreach (var resource in BasePageStatics.AppProvider.GetJavaScriptFiles())
                        {
                            assertResourceIsIntermediateInstallationPublicResourceWhenNecessary(resource);
                            markup.Append(getElement(resource));
                        }
                    },
                        () => {
                        var icons = new List <(ResourceInfo, string, string)>();

                        var faviconPng48X48 = BasePageStatics.AppProvider.FaviconPng48X48;
                        if (faviconPng48X48 != null)
                        {
                            assertResourceIsIntermediateInstallationPublicResourceWhenNecessary(faviconPng48X48);
                            icons.Add((faviconPng48X48, "icon", "48x48"));
                        }

                        var favicon = BasePageStatics.AppProvider.Favicon;
                        if (favicon != null)
                        {
                            assertResourceIsIntermediateInstallationPublicResourceWhenNecessary(favicon);
                            icons.Add((favicon, "icon", ""));
                        }

                        return(icons);
                    },
                        hideWarnings => {
                        var url = AppRequestState.Instance.Url;
                        if (AppRequestState.Instance.UserAccessible && AppRequestState.Instance.ImpersonatorExists)
                        {
                            url = new UserManagement.Pages.Impersonate(
                                url,
                                optionalParameterSetter: (specifier, parameters) =>
                                specifier.User = AppTools.User != null ? AppTools.User.Email : UserManagement.Pages.Impersonate.AnonymousUser).GetUrl();
                        }
                        return(new NonLiveLogIn(
                                   url,
                                   optionalParameterSetter: (specifier, parameters) => {
                            specifier.Password = ConfigurationStatics.SystemGeneralProvider.IntermediateLogInPassword;
                            specifier.HideWarnings = hideWarnings;
                        }).GetUrl());
                    },
                        () => {
                        if (!AppRequestState.Instance.UserAccessible || !AppRequestState.Instance.ImpersonatorExists ||
                            (ConfigurationStatics.IsIntermediateInstallation && !AppRequestState.Instance.IntermediateUserExists))
                        {
                            return(null);
                        }
                        return("User impersonation is in effect.",
                               new HyperlinkSetup(new UserManagement.Pages.Impersonate(AppRequestState.Instance.Url), "Change user").Append <ActionComponentSetup>(
                                   new ButtonSetup(
                                       "End impersonation",
                                       behavior: new PostBackBehavior(
                                           postBack: PostBack.CreateFull(
                                               id: "ewfEndImpersonation",
                                               modificationMethod: UserImpersonationStatics.EndImpersonation,
                                               actionGetter: () => new PostBackAction(
                                                   new ExternalResource(
                                                       EwfConfigurationStatics.AppConfiguration.DefaultBaseUrl.GetUrlString(
                                                           EwfConfigurationStatics.AppSupportsSecureConnections)))))))
                               .Materialize());
                    });
                    EwfUiStatics.Init(providerGetter.GetProvider <AppEwfUiProvider>("EwfUi"));
                    AuthenticationStatics.Init(
                        providerGetter.GetProvider <AppAuthenticationProvider>("Authentication"),
                        (user, code) => new UserManagement.Pages.LogIn(
                            "",
                            optionalParameterSetter: (specifier, parameters) => {
                        specifier.User = user;
                        specifier.Code = code;
                    }).GetUrl(),
                        destinationUrl => new UserManagement.Pages.ChangePassword(destinationUrl).GetUrl(disableAuthorizationCheck: true));
                    Admin.EntitySetup.Init(() => RequestDispatchingStatics.AppProvider.GetFrameworkUrlParent());
                    RequestDispatchingStatics.Init(providerGetter.GetProvider <AppRequestDispatchingProvider>("RequestDispatching"));

                    EwfInitializationOps.appInitializer = appInitializer;
                    appInitializer?.InitStatics();

                    executeWithAutomaticDatabaseConnections(AuthenticationStatics.InitAppSpecificLogicDependencies);
                    if (AuthenticationStatics.SamlIdentityProviders.Any() || ExternalFunctionalityStatics.SamlFunctionalityEnabled)
                    {
                        executeWithAutomaticDatabaseConnections(ExternalFunctionalityStatics.ExternalSamlProvider.InitAppSpecificLogicDependencies);
                    }

                    initTimeDataAccessState     = null;
                    EwfApp.FrameworkInitialized = true;
                },
예제 #5
0
        private void handleBeginRequest( object sender, EventArgs e )
        {
            if( !FrameworkInitialized ) {
                // We can't redirect to a normal page to communicate this information because since initialization failed, the request for that page will trigger
                // another BeginRequest event that puts us in an infinite loop. We can't rely on anything except an HTTP return code. Suppress exceptions; there is no
                // way to report them since even our basic exception handling may not work if the application isn't initialized.
                try {
                    set500StatusCode( "Initialization Failure" );
                }
                catch {}
                return;
            }

            ExecuteWithBasicExceptionHandling(
                delegate {
                    if( RequestState != null ) {
                        RequestState = null;
                        throw new ApplicationException( "AppRequestState was not properly cleaned up from a previous request." );
                    }

                    // This used to be just HttpContext.Current.Request.Url, but that doesn't work with Azure due to the use of load balancing. An Azure load balancer
                    // will bind to the ip/host/port through which all web requests should come in, and then the request is redirected to one of the server instances
                    // running this web application. For example, a user will request mydomain.com. In Azure, there may be two instances running this web site, on
                    // someIp:81 and someIp:82. For some reason, HttpContext.Current.Request.Url ends up using the host and port from one of these addresses instead of
                    // using the host and port from the HTTP Host header, which is what the client is actually "viewing". Basically, HttpContext.Current.Request.Url
                    // returns http://someIp:81?something=1 instead of http://mydomain.com?something=1. See
                    // http://stackoverflow.com/questions/9560838/azure-load-balancer-causes-400-error-invalid-hostname-on-postback.

                    var baseUrl = getRequestBaseUrl( Request );
                    if( !baseUrl.Any() ) {
                        setStatusCode( 400 );
                        return;
                    }
                    var appRelativeUrl = GetRequestAppRelativeUrl( Request, disableLeadingSlashRemoval: true );

                    // If the base URL doesn't include a path and the app-relative URL is just a slash, don't include this trailing slash in the URL since it will not be
                    // present in the canonical URLs that we construct and therefore it would cause problems with URL normalization.
                    var url = !getRequestBasePath( Request ).Any() && appRelativeUrl.Length == "/".Length ? baseUrl : baseUrl + appRelativeUrl;

                    // This blocks until the entire request has been received from the client.
                    // This won't compile unless it is assigned to something, which is why it is unused.
                    var stream = Request.InputStream;

                    RequestState = new AppRequestState( url );
                },
                false,
                true );
        }