custom application_start code for umbraco website
Asked Answered
H

5

7

I read that for umbraco to run my code on application startup I need to inherit from umbraco.Global and override Application_Start. I've done that with the following simple code which resides in it's own assembly referenced by the umbraco web site project, and in it's bin folder.

public class AtomicF1Global : umbraco.Global
{        
    protected override void Application_Start(object sender, EventArgs e)
    {
        base.Application_Start(sender, e);

        new WindsorStarter().Start();

        throw new Exception("Reached Custom Global");
    }
}

The exception is in there purely to prove to me it wasn't being called.

As far as I know all I need to do is what I've done. I don't need to update an umbraco table anywhere (as is the case when making a number of different modications to umbraco).

However, my code is never being called and I've not been able to find out why. Do I need to register something somewhere?

I've also checked to ensure "App_Global.asax.dll" is not present in the bin directory.

I have also tried creating a Global.asax in the umbraco site project that looks like this:

<%@ Application Language="C#" Inherits="umbraco.Global" %>
<%@ Import Namespace="atomicf1.domain" %>

<script runat="server">

    void Application_Start(object sender, EventArgs e) 
    {
        // Call Global base class first
        base.Application_Start(sender, e);


        // Code that runs on application startup
        new WindsorStarter().Start();

        throw new Exception("Reached Custom Global");

    }             
</script>

Version of umbraco is 4.7.1 (.NET 4.0).

Hers answered 28/2, 2012 at 23:12 Comment(0)
E
4

I created an empty MVC solution in Visual Studio and added Umbraco 6.x. Edited global.asax.cs and had the same problem as you: function not firing.

The solution seems easy but a bit tricky:

In the global.asax file (if you double click it, visual studio opens global.asax.cs, press "F7" or right click on global.asax and select "View Markup") you have to change the "Inherits" attribute. See original global.asax from umbraco:

<% Application Codebehind="Global.asax.cs" Inherits="Umbraco.Web.UmbracoApplication" Language="C#" %>

Change it to this:

<%@ Application Codebehind="Global.asax.cs" Inherits="YourGlobalClassName" Language="C#" %>

Note: if YourGlobalClassName is inside of a Namespace, make sure to include the namespace as well, like this:

<%@ Application Codebehind="Global.asax.cs" Inherits="YourNameSpace.YourGlobalClassName" Language="C#" %>

See also:

Original custom controller documentation from umbraco.

Similar question (addressed to umbraco 6): solution in stackoverflow.

Expurgate answered 17/6, 2013 at 11:20 Comment(0)
I
2

Implementing your own global.asax is the correct way as it will run upon application start.

I have implemented my global.asax in a similar way to yours, however I place the code in a separate CS file in a separate project - but then that's just my way.

public class Global : umbraco.Global
{
    protected override void Application_Start(object sender, System.EventArgs e)
    {
        base.Application_Start(sender, e);

        XmlConfigurator.Configure();
        ILog log = LogManager.GetLogger(typeof (Global));
        log.Debug("Application started");
    }

}

Looking at the differences, you would need to add protected override to your method.

Personally, I always add logging (using log4net) to my global.cs file so I can ensure that my logging is up and running and that the application has restarted.

If your code is not being picked up, you may want to try amending the web.config to force a application restart, but also step through with the debugger to make sure that your code just isn't being reached for some other reason.

Ioves answered 2/3, 2012 at 11:53 Comment(1)
Thanks. I'm using exactly your method in my AtomicF1Global class but it's just not getting fired. I've tried touching the web.config and restarting the app pool etc. I've no idea why, because everything I've read points to what I initially tried (and also your solution) as being the way to go.Hers
J
1

If you want code to run on application start up, the way you'd normally do it is to create a class that inherits from ApplicationBase. Public classes that inherit from this are called when the Umbraco application starts up. Here's some example code from one of the startup events that we use on one of our Umbraco sites:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.web;
using umbraco.BasePages;

namespace MySite.Events
{
    public class EventHandlers : ApplicationBase
    {
        public EventHandlers()
        {
            //put your code to run on app startup here
        }
    }
}
Jotunheim answered 1/3, 2012 at 10:29 Comment(3)
I've marked this down because this is not the correct way to add code to run upon start-up. This is how you would extend Umbraco events, e.g. Moving or copying a node. If you add logging to this, you will see that this might actually be instantiated multiple times within an application lifetime.Ioves
FWIW I've tried this method too, after reading it in a Matt Brailsford blog post.Hers
@Ioves But if you need to run things that depend on the umbraco core you could use this. Running it in the Application_Start would not give you access to nodes in the cached xml document. So this is a good method for sites prior to the introduction of the IApplicationStartupHandlerZofiazoha
C
1

I would use the WebActivator package. Then you can make your code run without bothering with global.asax and overriding Umbraco methods.

See this blog post by Bart Wullems for a quick start.

Criminate answered 21/3, 2012 at 11:4 Comment(1)
that WebActivator link gone dead. i think it sits here now nuget.org/packages/WebActivatorExSacks
H
1

I appreciate that this is a very old question, but this is one of the few options I found when searching on a similar issue.

The solution I've settled on differs from the ones mentioned in this thread so I thought I'd also offer it up.

I went ahead and wrote a CustomWebModule which can sit between the web request and any requests inbound into umbraco.

Step one was to write a custom IHttpModule implementation

namespace My.Application.Namespace
{
    public class CustomWebModule : IHttpModule
    {
        static void AuthenticateRequest(object sender, EventArgs e){
            // DO ALL FANCY STUFF in my app and then make calls to the 
            // KEY umbraco functions from umbraco.core.security.AuthenticationExtensions 
            // "AuthenticateCurrentRequest" function.
            // 
            // specifically: setting the GenericPrincipal and related entities.
        }

        public void Dispose()
        {
            //throw new NotImplementedException();
            // make sure you don't write a memory leak!
            // dispose of everything that needs it!
        }

        public void Init(HttpApplication app)
        {
            app.AuthenticateRequest += AuthenticateRequest; 
        }
    }
}

note that the calls required in the "fancy stuff" section are listed in the Umbraco core codebase here:

https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Core/Security/AuthenticationExtensions.cs

then add keys to the web.config

<system.web>
    <httpModules>
        <add name="CustomWebModule" type="My.Application.Namespace.CustomWebModule"/>

and

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
            <remove name="CustomWebModule"/>
            <add name="CustomWebModule" type="My.Application.Namespace.CustomWebModule"/>
Hamate answered 6/4, 2015 at 13:51 Comment(1)
Kinda harsh, but i like itSacks

© 2022 - 2024 — McMap. All rights reserved.