So I had this problem where I absolutely needed to use the IoC of the solution I was working (and Am working) on but also needed to use an HttpModule to redirect the request before it even got in the container.
Well I found some ways to do it that weren't what I needed nor wanted.
I didn't want to add a dependency to a library to use it on just an HttpModule.
Well after fiddling a little with the module I got to a success.
It may not be pretty, it may cause some eye soreness, but it's working!
It will only actually use the EndRequest once and a simple boolean comparison isn't that costly. Also if for some reason the service isn't resolved propperly, it will use the EndRequest again. "Simple"!
I hope to have helped all the others that had the same problem as me!
public sealed class ChannelRedirectionModule : IHttpModule
{
private readonly Func<IChannelRedirectionService> _channelRedirectionService;
private static bool _firstCall = true;
public ChannelRedirectionModule()
{
_channelRedirectionService = DependencyResolver.Current.GetService<Func<IChannelRedirectionService>>();
}
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) =>
{
if (!_firstCall)
{
Redirect(sender, e);
}
};
context.EndRequest += (sender, e) =>
{
if (_firstCall)
{
Redirect(sender, e);
}
};
}
private void Redirect(object sender, EventArgs e)
{
var app = (sender as HttpApplication);
var channelRedirectionService = _channelRedirectionService();
if (channelRedirectionService == null)
{
_firstCall = true;
return;
}
_firstCall = false;
string redirectUrl = channelRedirectionService.GetRedirectAddressForChannelId(app.Request);
if (!string.IsNullOrEmpty(redirectUrl))
{
app.Response.Redirect(redirectUrl);
}
}
public void Dispose()
{
//there's realy nothing to be disposed here,
//but we're enforced to have this by the IHttpModule interface...
}
}
Related
I am trying to mock up the following Transfer request.
I have tried using Moq but it doesn't like the fact that it is a method call. Any ideas?
I have tried using shims but it hasn't exactly made sense to me. https://social.msdn.microsoft.com/Forums/vstudio/en-US/4e423407-300d-46ba-bfc9-30465fb18f07/how-to-fake-httpcontextcurrent-using-shim?forum=vstest
I tried mocking http context this way but it didn't work either.
https://justinchmura.com/2014/06/26/mock-httpcontext/
public class MyModule1 : IHttpModule
{
/// <summary>
/// You will need to configure this module in the Web.config file of your
/// web and register it with IIS before being able to use it. For more information
/// see the following link: https://go.microsoft.com/?linkid=8101007
/// </summary>
#region IHttpModule Members
public void Dispose()
{
//clean-up code here.
}
public void Init(HttpApplication context)
{
// Below is an example of how you can handle LogRequest event and provide
// custom logging implementation for it
context.LogRequest += new EventHandler(OnLogRequest);
context.BeginRequest += new EventHandler(OnBeginRequest);
}
private void OnBeginRequest(object sender, EventArgs e)
{
onbegin(new HttpContextWrapper(((HttpApplication)sender).Context));
}
private void onbegin(HttpContextBase context)
{
// other header stuff goes here
context.Server.TransferRequest("bobsyouruncle", true);
}
#endregion
public void OnLogRequest(Object source, EventArgs e)
{
//custom logging logic can go here
}
Similar to an approach I took in an answer provided here
How to test HttpApplication events in IHttpModules
You can create a factory method/function that wraps the current tightly coupled implementation concerns in abstractions that would allow for better mocking and testability
Refactored module
public class MyModule1 : IHttpModule {
public void Dispose() {
//clean-up code here.
}
public void Init(HttpApplication application) {
// Below is an example of how you can handle LogRequest event and provide
// custom logging implementation for it
application.LogRequest += new EventHandler(OnLogRequest);
application.BeginRequest += new EventHandler(OnBeginRequest);
}
public Func<object, HttpContextBase> GetContext = (object sender) => {
return new HttpContextWrapper(((HttpApplication)sender).Context);
};
public void OnBeginRequest(object sender, EventArgs e) {
var context = GetContext(sender);
onbegin(context);
}
private void onbegin(HttpContextBase context) {
// other header stuff goes here
context.Server.TransferRequest("bobsyouruncle", true);
}
public void OnLogRequest(Object source, EventArgs e) {
//custom logging logic can go here
}
//...
}
The GetContext factory function can be replaced when testing to use a mock.
For example
[TestMethod]
public void Server_Should_Transfer() {
//Arrange
var server = new Mock<HttpServerUtilityBase>();
var context = new Mock.<HttpContextBase>();
context.Setup(_ => _.Server).Returns(server.Object);
var sut = new MyModule1();
//replace with mock context for test
sut.GetContext = (object sender) => context.Object;
//Act
sut.OnBeginRequest(new object(), EventArgs.Empty);
//Assert
server.Verify(_ => _.TransferRequest("bobsyouruncle", true), Times.AtLeastOnce);
}
I need the following logic implemented:
a thread to which you can subscribe/unsubscribe methods at runtime.
It's fine for all these methods to have an header such as (Object sender, EventArgs e) and to return void.
These methods scope must be the scope of the class where they are defined lexically.
There's no guarantee about the order of execution
I've come up with the following implementation, which seems to do exactly what I need: basically I start an internal thread which triggers an event each x milliseconds. You can subscribe/unsubscribe delegates to this event through appropriate methods.
Before sticking to it I'd like to know if there may be subtle issues following this approach.
public class Orchestrator
{
private Thread _mainThread;
private event MethodDelegate _mainEvent;
public delegate void MethodDelegate (Object sender, EventArgs e);
private bool _stop = false;
private short _ms = 100;
public short PollingInterval { get { return _ms; }
set
{
_ms = value;
}
}
public Orchestrator()
{
_mainThread = new Thread(new ThreadStart(_execute));
}
public void Start()
{
_stop = false;
_mainThread.Start();
}
public void Stop()
{
_stop = true;
}
public void Clear()
{
_mainEvent = null;
}
public void Push(MethodDelegate method)
{
_mainEvent += method;
}
public void Pop(MethodDelegate method)
{
_mainEvent -= method;
}
private void _execute()
{
while(!_stop)
{
if (_mainEvent != null)
try
{
_mainEvent(this, new EventArgs());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Thread.Sleep(_ms);
}
}
}
That's basically fine. You need to make _stop volatile. In C# the event accessor methods are thread-safe so that works fine.
The exception handling is very questionable. Do you really want to spam errors to the console? Define an event OnError and report errors to the consumer of your class.
You could use a timer or await Task.Delay to save a thread. This would make sense if there are a lot of such class instances at the same time. If there is just one this is likely not worth the effort.
You have a race condition which could cause a NullReferenceException, in:
while(!_stop)
{
if (_mainEvent != null)
try
{
_mainEvent(this, new EventArgs());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Thread.Sleep(_ms);
}
Some other thread could unsubscribe from the event or call Clear() inbetween if (_mainEvent != null) and the call of _mainEvent.
To avoid this, you should copy _mainEvent into a local variable and check that against null, and use that instead:
var mainEvent = _mainEvent;
if (mainEvent != null)
try
{
mainEvent(this, new EventArgs());
In any case, I think you should be using a Timer for this rather than rolling-your-own.
I would like to know if there is a mechanism to intercept all Bindings, so that I can suppress the updating on a specific condition?
Pseudo Code:
public class Utils
{
public void RegisterInterceptionOfBinding()
{
WpfBindingMechanism.OnSourceUpdating += SourceUpdating;
WpfBindingMechanism.OnTargetUpdating += TargetUpdating;
}
private void SourceUpdating(object sender, SourceUpdatingEventArgs args)
{
if (DoSomeMagicConditionChecking)
{
args.Cancel = true;
}
}
private void TargetUpdating(object sender, SourceUpdatingEventArgs args)
{
if (DoSomeMagicConditionChecking)
{
args.Cancel = true;
}
}
}
I am searching for a mechanism that works on ALL Bindings in the entire WPF Application.
You might be looking to use the TypeDescriptionProvider class.
Here is a forum post on MSDN that might answer your question:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/d8046807-ac1a-4d1f-81f2-6a2f93dab78a/intercept-binding-mechanism
I need to be able to trigger a event whenever an object is added to a Queue<Delegate>.
I created a new class that extends Queue:
public delegate void ChangedEventHandler(object sender, EventArgs e);
public class QueueWithChange<Delegate> : Queue<Delegate>
{
public event ChangedEventHandler Changed;
protected virtual void OnChanged(EventArgs e) {
if (Changed != null)
{
Changed(this, e);
}
}
}
And then attached the event from another class, like such:
QueueWithChange<TimerDelegate> eventQueue = new QueueWithChange<TimerDelegate>();
//
eventQueue.Changed += new ChangedEventHandler(delegate(object s, EventArgs ex) {
//This event is not being triggered, so this code is unreachable atm...and that is my problem
if (eventQueue.Count > 0)
{
eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) });
actionTimer.Stop();
}
});
But whenever I enqueue an object (eventQueue.Enqueue(something)), the attached event is not being fired.
What am I missing here?
If you mean the non-generic Queue class, then you can just override Enqueue:
public override void Enqueue(object obj)
{
base.Enqueue(obj);
OnChanged(EventArgs.Empty);
}
However, if you mean the generic Queue<T> class, then note that there is no suitable virtual method to override. You might do better to encapsulate the queue with your own class:
(** important edit: removed base-class!!! **)
class Foo<T>
{
private readonly Queue<T> queue = new Queue<T>();
public event EventHandler Changed;
protected virtual void OnChanged()
{
if (Changed != null) Changed(this, EventArgs.Empty);
}
public virtual void Enqueue(T item)
{
queue.Enqueue(item);
OnChanged();
}
public int Count { get { return queue.Count; } }
public virtual T Dequeue()
{
T item = queue.Dequeue();
OnChanged();
return item;
}
}
However, looking at your code, it seems possible that you are using multiple threads here. If that is the case, consider a threaded queue instead.
I just did write up on what I call a TriggeredQueue. It's inspired the answer by Marc Gravell.
You can find my post here: http://joesauve.com/triggeredqueuet
And the Gist here: http://gist.github.com/jsauve/b2e8496172fdabd370c4
It has four events:
WillEnqueue
WillDequeue
DidEnqueue
DidDequeue
You can hook into any of these like so:
YourQueue.WillEnqueue += (sender, e) => {
// kick off some process
};
YourQueue.DidEnqueue += (sender, e) => {
// kick off some process
// e.Item provides access to the enqueued item, if you like
};
YourQueue.WillDequeue += (sender, e) => {
// kick off some process
};
YourQueue.DidDequeue += (sender, e) => {
// kick off some process
// e.Item provides access to the dequeued item, if you like
};
One neat trick is that you can use the DidDequeue method to kick off some process to ensure that the queue is full by making a web request or loading some data from a filesystem, etc. I use this class in Xamarin mobile apps to ensure that data and images are pre-cached in order to provide a smooth user experience, instead of loading images AFTER they scroll onto the screen (like you might see in Facebook and countless other apps).
try
public new void Enqueue(Delegate d)
{
base.Enqueue(d);
OnChanged(EventArgs.Empty);
}
You have to override Enqueue, to call OnChanged.
I'm working on an IIS module that, when a web page request is made, it looks over the data being passed back to the browser and replaces certain keywords with approved keywords. I realize there are multiple ways to do this, but for our purposes an IIS module will work best.
How can I read the stream of data being send back to the browser into a string so that I can convert keywords as needed?
Any help would be GREATLY appreciated!
Here's the code:
namespace MyNamespace
{
class MyModule : IHttpModule
{
private HttpContext _current = null;
#region IHttpModule Members
public void Dispose()
{
throw new Exception("Not implemented");
}
public void Init(HttpApplication context)
{
_current = context.Context;
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
#endregion
public void context_PreRequestHandlerExecute(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpRequest request = app.Context.Request;
}
}
There are two ways:
Using Response Filters
https://web.archive.org/web/20211029043851/https://www.4guysfromrolla.com/articles/120308-1.aspx
Handle the PreRequestHandlerExecute event of the application as it is run just before the IHttpHandler processes the page itself:
public class NoIndexHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += AttachNoIndexMeta;
}
private void AttachNoIndexMeta(object sender, EventArgs e)
{
var page = HttpContext.Current.CurrentHandler as Page;
if (page != null && page.Header != null)
{
page.Header.Controls.Add(new LiteralControl("<meta name=\"robots\" value=\"noindex, follow\" />"));
}
}
}