I'm writing an app where 3rd party vendors can write plugin DLLs and drop them into the web app's bin directory. I want the ability for these plugins to be able to register their own HttpModules if necessary.
Is there anyway that I can add or remove HttpModules from and to the pipeline at runtime without having a corresponding entry in the Web.Config, or do I have to programmatically edit the Web.Config when adding / removing modules? I know that either way is going to cause an AppDomain restart but I'd rather be able to do it in code than having to fudge the web.config to achieve the same effect.
It has to be done at just the right
time in the HttpApplication life cycle
which is when the HttpApplication
object initializes (multiple times,
once for each instance of
HttpApplication). The only method
where this works correct is
HttpApplication Init().
To hook up a module via code you can
run code like the following instead of
the HttpModule definition in
web.config:
public class Global : System.Web.HttpApplication
{
// some modules use explicit interface implementation
// by declaring this static member as the IHttpModule interface
// we work around that
public static IHttpModule Module = new xrnsToashxMappingModule();
public override void Init()
{
base.Init();
Module.Init(this);
}
}
All you do is override the HttpApplication's Init() method and
then access the static instance's Init
method. Init() of the module hooks up
the event and off you go.
Via Rick Strahl's blog
Realize this is an old question, but asp.net 4 provides some new capabilities that can help here.
Specifically, ASP.NET 4 provides a PreApplicationStartMethod capability that can be used to add HttpModules programmatically.
I just did a blog post on that at http://www.nikhilk.net/Config-Free-HttpModule-Registration.aspx.
The basic idea is you create a derived HttpApplication that provides ability to add HttpModules dynamically at startup time, and it then initializes them into the pipeline whenever each HttpApplication instance is created within the app-domain.
The dll Microsoft.Web.Infrastructure.dll has a method for this inside the class DynamicModuleUtility.
The dll is shipped with WebPages 1.0
public static class PreApplicationStartCode
{
private static bool _startWasCalled;
public static void Start()
{
if (_startWasCalled) return;
_startWasCalled = true;
DynamicModuleUtility.RegisterModule(typeof(EventTriggeringHttpModule));
}
}
This worked for me for dynamic registration.
RegisterModule(typeof(RequestLoggerModule));
public class RequestLoggerModule : IHttpModule
{ ... }
https://learn.microsoft.com/en-us/dotnet/api/system.web.httpapplication.registermodule?view=netframework-4.7.2
In new versions of ASP MVC you can use Package Manager to add a reference to WebActivatorX and then do something like this
using WhateverNameSpacesYouNeed;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourApp.SomeNameSpace.YourClass), "Initialize")]
namespace YourApp.SomeNameSpace
{
public static void Initialize()
{
DynamicModuleUtility.RegisterModule( ... the type that implements IHttpModule ... );
}
}
Related
I very read for this problem but i can not fixed this so i think create a new question in this site.
HttpContext.Current.GetOwinContext();
i want get GetOwinContext values with above code . above code there are in my startup.cs
[assembly: OwinStartupAttribute(typeof(OwinTest.Startup))]
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var c = HttpContext.Current.GetOwinContext();
}
}
and i get this error
//No owin.Environment item was found in the context
but var c = HttpContext.Current.GetOwinContext(); work for me in HomeController fine.!
I just get GetOwinContext in my startup.cs class.
thankfull
You can't do that. The OWIN context does not exist without a request, and the Startup class only runs once for the application, not for each request. Your Startup class should initialize your middleware and your application and the middleware and the application should access the OWIN context when needed.
As mentioned, what you are asking isn't possible. However, depending on your requirements, the following is possible and gives you access within the context of creating object instances. This is something I needed in order to check for whether an instance was already added else where (I have multiple startup classes in different projects).
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// Ensure we have our "main" access setup
app.CreatePerOwinContext<DataAccessor>(
(options, owinContext) =>
{
// Check that an instance hasn't already been added to
// the OwinContext in another plugin
return owinContext.Get<DataAccessor>() ?? DataAccessor.CreateInstance(options, owinContext);
}
);
}
Within the CreatePerOwinContext we have access to the OwinContext, so we can access it at the point of creating a new type. This might not help everyone as it's a little more specific to a person's needs, but is useful to know.
I'm trying to implement an VirtualPathProvider for SharePoint 2010/2013 (Server and Foundation). So far I've implemented subclasses of System.Web.Hosting.VirtualPathProvider, System.Web.Hosting.VirtualFile and System.Web.Hosting.VirtualDirectory.
I wanted to use a feature with FeatureReceiver class to register the new VPP with the HostingEnvironment. But since I have implemented the line
HostingEnvironment.RegisterVirtualPathProvider(new MyVPProvider());
into the FeatureActivated method, VisualStudio's debug deployment fails with:
Error occurred in deployment step 'Activate Features': Operation is not valid due to the current state of the object.
I have no idea what I am doing wrong. Maybe a FeatureReceiver is the wrong place to register the VPP?
I've already searched the web for an tutorial or example but I didn't find any suitable. Any hint on how to develop a VirtualPathProvider for SharePoint is much appreciated! Thanks in advance.
--
Robert Vogel
You need to write an IHttpModule implementation which registers your virtual path provider ones.
Maybe this link helps you: SharePoint 2007 as a WCF host - Step #4, Write a Virtual Path Provider
using System.Web;
public class MyVirtualPathProviderRegisterModule : IHttpModule
{
static bool _Initialized = false;
static object _Lock = new object();
public void Init(HttpApplication app)
{
if (!_Initialized)
lock(_Lock)
if(!_Initialized)
{
HostingEnvironment.RegisterVirtualPathProvider(new MyVirtualPathProvider());
_Initialized = true;
}
}
public void Dispose() {}
}
How do I register a global message handler in a MVC application?
I tried registering it in my Global.asax.cs, but this handler never gets called whenever I access any of my endpoints in all my controllers that inherit from System.Web.Mvc.Controller.
However, it does get called when I access routes all my controllers that inherit from System.Web.Http.ApiController.
This is what I put in my Global.asax.cs:
protected void Application_Start()
{
//other initializing stuff here
**GlobalConfiguration.Configuration.MessageHandlers.Add(new AuthenticationHandler());**
}
I believe you're looking for Filters. You could build something like this:
public class MyAuthorizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
// do your work here
}
}
and then add it to the global filters list in Application_Start:
GlobalConfiguration.Configuration.Filters.Add(new MyAuthorizationFilter());
I have a .Net MVC web application (Not WebAPI), and I want to intercept all calls to the web app before they reach the controller, check for a value in the request headers, and do something if the value isn't present (such as presenting a 404). What's the ideal way to do this? Keep in mind this is not a Web API application, just a simple web application.
Depending on what specifically you want to do, you could use a default controller which all other controllers extend. That way you can override OnActionExecuting or Initialize and do your check there.
public class ApplicationController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
//do your stuff here
}
}
public class YourController : ApplicationController
{
}
You're looking for global action filters.
Create a class that inherits ActionFilterAttribute, override OnActionExecuting() to perform your processing, and add an instances to global filter collection in Global.asax.cs (inside RegisterGlobalFilters())
My project has no "global.asax" for various reasons and I can't change that (it's a component). Also, I have no access to web.config, so an httpModule is also not an option.
Is there a way to handle application-wide events, like "BeginRequest" in this case?
I tried this and it didn't work, can someone explain why? Seems like a bug:
HttpContext.Current.ApplicationInstance.BeginRequest += MyStaticMethod;
No, this is not a bug. Event handlers can only be bound to HttpApplication events during IHttpModule initialization and you're trying to add it somewhere in the Page_Init(my assumption).
So you need to register a http module with desired event handlers dynamically. If you're under .NET 4 there is a good news for you - there is PreApplicationStartMethodAttribute attribute (a reference: Three Hidden Extensibility Gems in ASP.NET 4):
This new attribute allows you to have
code run way early in the ASP.NET
pipeline as an application starts up.
I mean way early, even before
Application_Start.
So the things left are pretty simple: you need to create your own http module with event handlers you want, module initializer and attribute to your AssemblyInfo.cs file . Here is a module example:
public class MyModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
public void Dispose()
{
}
void context_BeginRequest(object sender, EventArgs e)
{
}
}
To register module dynamically you could use DynamicModuleUtility.RegisterModule method from the Microsoft.Web.Infrastructure.dll assembly:
public class Initializer
{
public static void Initialize()
{
DynamicModuleUtility.RegisterModule(typeof(MyModule));
}
}
the only thing left is to add the necessary attribute to your AssemblyInfo.cs:
[assembly: PreApplicationStartMethod(typeof(Initializer), "Initialize")]