Extending global.asax in Umbraco 4.7 for dependency injection - dependency-injection

Im using umbraco v 4.7.1 (Assembly version: 1.0.4281.20201) and have a project where I must extend the global.asax file.
Please not the following
I have tried this, http://blog.mattbrailsford.com/2010/07/11/registering-an-application-start-event-handler-in-umbraco/, didn't work in 4.7
it is Global.asax I need to extend since I'm working with dependency injection
I cannot delete the App_global.asax.dll file (as some may suggest) since it will regenerate everytime I restart or rebuild my project
Here is my implementation,
using Project.Umbraco.DependencyInjection;
using Project.Umbraco.IoC;
using Microsoft.Practices.Unity;
using System;
using System.Diagnostics;
using umbraco;
namespace Project.Umbraco.App_Start
{
public class MyGlobal : Global, IContainerAccessor
{
///
/// Returns the IoC container
/// IContainerAccessor
///
public IUnityContainer Container
{
get
{
return MvcUnityContainer.Instance.Container;
}
}
protected override void Application_Start(object sender, EventArgs e)
{
base.Application_Start(sender, e);
Debug.WriteLine("Application start");
}
protected override void Application_BeginRequest(object sender, EventArgs e)
{
base.Application_BeginRequest(sender, e);
Debug.WriteLine("Application start");
}
//protected void Session_Start(object sender, EventArgs e) {}
//protected void Application_AuthenticateRequest(object sender, EventArgs e) {}
//protected void Application_Error(object sender, EventArgs e) {}
//protected void Session_End(object sender, EventArgs e) {}
//protected void Application_End(object sender, EventArgs e) {}
}
}
The implementation seems as if should work, maybe I've just placed this in the wrong namespace or something?
Thanks for any help
T

From Umbraco 4.8.0 and onwards, the App_global.asax.dll is no longer needed, so you might want to consider upgrading to a newer version.
In 4.7 though, you could simply use the PreApplicationStart method by creating a class that looks a little something like this:
using System.Linq;
using System.Web.Routing;
using System.Web.Http;
using CustomerName.Extensions;
[assembly: System.Web.PreApplicationStartMethod(typeof(AppStart), "PreStart")]
namespace CustomerName.Extensions
{
public static class AppStart
{
public static void PreStart()
{
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Of course, instead of defining WebAPI routes, you could insert your DI code.

Related

Asp.Net MVC Controller Multi-Language

Is there a way to make http://myapp.com/Orders, http://myapp.com/Pedidos, http://myapp.com/Solicetudes reach the same OrdersController??? Maybe something like
[AlternativeNames("Pedidos","Solicitudes","Bla","Ble")]
public class HomeController : Controller
{
...
}
You can set this at the Route level.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("Content/{*pathInfo}");
routes.MapRoute("Order-Controller-Spanish", "Pedidos", new { controller = "Order" });
routes.MapRoute("Order-Controller-English", "Orders", new { controller = "Order" });
}
In your global.asax :
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}

Global.asax in Umbraco 6

I had the following in my Global.asax (Umbraco 4.7)
Application_Start
Application_EndRequest
Application_Error
Session_Start
Session_End
Now I have upgraded to Umbraco 6.0.3, which global.asax inherits from Umbraco.Web.UmbracoApplication
Where do I put my event handlers (and what are the equivalent method names)?
This is what I found so far.
You can create your own class
public class Global : Umbraco.Web.UmbracoApplication
{
public void Init(HttpApplication application)
{
application.PreRequestHandlerExecute += new EventHandler(application_PreRequestHandlerExecute);
application.EndRequest += (new EventHandler(this.Application_EndRequest));
//application.Error += new EventHandler(Application_Error); // Overriding this below
}
protected override void OnApplicationStarted(object sender, EventArgs e)
{
base.OnApplicationStarted(sender, e);
// Your code here
}
private void application_PreRequestHandlerExecute(object sender, EventArgs e)
{
try
{
if (Session != null && Session.IsNewSession)
{
// Your code here
}
}
catch(Exception ex) { }
}
private void Application_BeginRequest(object sender, EventArgs e)
{
try { UmbracoFunctions.RenderCustomTree(typeof(CustomTree_Manage), "manage"); }
catch { }
}
private void Application_EndRequest(object sender, EventArgs e)
{
// Your code here
}
protected new void Application_Error(object sender, EventArgs e)
{
// Your error handling here
}
}
And have Global.asax inherit from your class
<%# Application Codebehind="Global.asax.cs" Inherits="Global" Language="C#" %>
Alternative method: Inherit ApplicationEventHandler - but it's not working for me

MVC 4 Global Exception Filter how to implement?

How do I implement a global exception handler in MVC4 as it seems to be different from MVC3.
Not sure how to implement the following:
public class ErrorHandlerAttribute: System.Web.Mvc.FilterAttribute,
IExceptionFilter
{
public Task ExecuteExceptionFilterAsync(
HttpActionExecutedContext actionExecutedContext,
CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
Unfortunately the link provided in Eric Leschinski's commet only shows how to implement the System.Web.Mvc.IExceptionFilter interface, and not the System.Web.Http.Filters.IExceptionFilter interface. The first is used in regular MVC controllers, while the second targets ApiCotrollers.
Here is a simple class example I came up with for logging unhandled exceptions thrown in my ApiControllers:
public class ExceptionLoggerFilter: IExceptionFilter
{
public ExceptionLoggerFilter(Logger logger)
{
this.logger = logger;
}
public bool AllowMultiple { get { return true; } }
public Task ExecuteExceptionFilterAsync(
HttpActionExecutedContext actionExecutedContext,
CancellationToken cancellationToken)
{
return Task.Factory.StartNew(() =>
{
logger.Error("web service error", actionExecutedContext.Exception);
}, cancellationToken);
}
private Logger logger;
}
And all you have to do to enable this filter is register it in yours Global.asax Application_Start method:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// allocate filter and add it to global configuration
var exceptionLogger = new ExceptionLoggerFilter(Container.Get<Logger>());
GlobalConfiguration.Configuration.Filters.Add(exceptionLogger);
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
I hope this helps other googlers out there!
The way I created an exception handler for MVC part of it, I created a class that implemented IExceptionFilter
public class MVCExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
Trace.TraceError(filterContext.Exception.ToString());
}
}
You then register it in the Global.asax.cs
inside protected void Application_Start()
The method already contains the line
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
So, you will need to add this line ABOVE it
GlobalFilters.Filters.Add(new MVCExceptionFilter());

ASP.NET MVC 4 intercept all incoming requests

Is there a way for me to catch all incoming requests to my ASP.NET MVC 4 app and run some code before continuing the request onward to the specified controller/action?
I need to run some custom auth code with existing services, and to do this properly, I'll need to be able intercept all incoming requests from all clients to double check some things with the other service.
The most correct way would be to create a class that inherits ActionFilterAttribute and override OnActionExecuting method. This can then be registered in the GlobalFilters in Global.asax.cs
Of course, this will only intercept requests that actually have a route.
You can use a HttpModule to accomplish this. Here is a sample I use to calculate the process time for all requests:
using System;
using System.Diagnostics;
using System.Web;
namespace Sample.HttpModules
{
public class PerformanceMonitorModule : IHttpModule
{
public void Init(HttpApplication httpApp)
{
httpApp.BeginRequest += OnBeginRequest;
httpApp.EndRequest += OnEndRequest;
httpApp.PreSendRequestHeaders += OnHeaderSent;
}
public void OnHeaderSent(object sender, EventArgs e)
{
var httpApp = (HttpApplication)sender;
httpApp.Context.Items["HeadersSent"] = true;
}
// Record the time of the begin request event.
public void OnBeginRequest(Object sender, EventArgs e)
{
var httpApp = (HttpApplication)sender;
if (httpApp.Request.Path.StartsWith("/media/")) return;
var timer = new Stopwatch();
httpApp.Context.Items["Timer"] = timer;
httpApp.Context.Items["HeadersSent"] = false;
timer.Start();
}
public void OnEndRequest(Object sender, EventArgs e)
{
var httpApp = (HttpApplication)sender;
if (httpApp.Request.Path.StartsWith("/media/")) return;
var timer = (Stopwatch)httpApp.Context.Items["Timer"];
if (timer != null)
{
timer.Stop();
if (!(bool)httpApp.Context.Items["HeadersSent"])
{
httpApp.Context.Response.AppendHeader("ProcessTime",
((double)timer.ElapsedTicks / Stopwatch.Frequency) * 1000 +
" ms.");
}
}
httpApp.Context.Items.Remove("Timer");
httpApp.Context.Items.Remove("HeadersSent");
}
public void Dispose() { /* Not needed */ }
}
}
And this is how you register the module in Web.Config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="PerformanceMonitorModule" type="Sample.HttpModules.PerformanceMonitorModule" />
</modules>
<//system.webServer>
I think that what you search for is this:
Application_BeginRequest()
http://www.dotnetcurry.com/showarticle.aspx?ID=126
You put it in Global.asax.cs.
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Request.....;
}
I use this for debugging purposes but I am not sure how good solution it is for your case.
I'm not sure about MVC4 but I think it is fairly similar to MVC5. If you have created a new web project -> look in Global.asax and you should see the following line FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); in the method Application_Start().
RegisterGlobalFilters is a method in the file FilterConfig.cs located in the folder App_Start.
As #YngveB-Nilsen said ActionFilterAttribute is the way to go in my opinion. Add a new class that derives from System.Web.Mvc.ActionFilterAttribute. This is important because System.Web.Http.Filters.ActionFilterAttribute will fail with the following exception for example.
The given filter instance must implement one or more of the following
filter interfaces: System.Web.Mvc.IAuthorizationFilter,
System.Web.Mvc.IActionFilter, System.Web.Mvc.IResultFilter,
System.Web.Mvc.IExceptionFilter,
System.Web.Mvc.Filters.IAuthenticationFilter.
Example that writes the request to the debug window:
public class DebugActionFilter : System.Web.Mvc.ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
Debug.WriteLine(actionContext.RequestContext.HttpContext.Request);
}
}
In FilterConfig -> RegisterGlobalFilters -> add the following line: filters.Add(new DebugActionFilter());.
You can now catch all incoming requests and modify them.

How to resolve an user repository using Windsor IoC at the start of the application?

I get an error message "Object reference not set to an instance of an object." when I try to use an UserRepos repository. Question is how can I resolve user repository at the start of the application (ASP.NET MVC) What is wrong here?
public class MyApplication : HttpApplication
{
public IUserRepository UserRepos;
public IWindsorContainer Container;
protected void Application_Start()
{
Container = new WindsorContainer();
// Application services
Container.Register(
Component.For<IUserRepository>().ImplementedBy<UserRepository>()
);
UserRepos = Container.Resolve<IUserRepository>();
}
private void OnAuthentication(object sender, EventArgs e)
{
if (Context.User != null)
{
if (Context.User.Identity.IsAuthenticated)
{
//Error here "Object reference not set to an instance of an object."
var user = UserRepos.GetUserByName(Context.User.Identity.Name);
var principal = new MyPrincipal(user);
Thread.CurrentPrincipal = Context.User = principal;
return;
}
}
}
}
Thank you for helping me!
The cause of this exception is a misunderstanding of the HttpApplication lifecycle. These articles explain it quite well:
http://ayende.com/Blog/archive/2006/09/10/SolvingTheHttpModuleMess.aspx
http://blog.andreloker.de/post/2008/05/HttpApplication-instances.aspx
in your case, this would be the correct container usage:
public class MyApplication: HttpApplication {
private static IWindsorContainer container;
protected void Application_Start() {
container = new WindsorContainer();
... registrations
}
private void OnAuthentication(object sender, EventArgs e) {
var userRepo = container.Resolve<IUserRepository>();
... code that uses userRepo
}
}

Resources