I am trying to execute some code in the application start of an HTML Module. Since the Init() gets fired multiple times, is there a reliable flag to tell me if the application started or not?
public class Module : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
//clean-up code here.
}
public void Init(HttpApplication context)
{
//PROCESS ON APPLICATION START EVENT
this.OnApplicationStart(context);
}
#endregion
public void OnApplicationStart(HttpApplication context)
{
if (!application started??) //FRAMEWORK FLAG?
//DO SOMETHING
}
}
You could use a flag:
public class Module : IHttpModule
{
private static bool isStarted = false;
private static object syncRoot = new object();
public void Dispose()
{
//clean-up code here.
}
public void Init(HttpApplication context)
{
if (!isStarted)
{
lock (syncRoot)
{
if (!isStarted)
{
//PROCESS ON APPLICATION START EVENT
this.OnApplicationStart(context);
isStarted = true;
}
}
}
}
public void OnApplicationStart(HttpApplication context)
{
//DO SOMETHING
}
}
As a better alternative to using HttpModules to perform this task if you are targetting .NET 4.0 or later I would recommend you using WebActivator which is a very handy package based on Microsoft.Web.Infrastructure allowing you to subscribe to events such as Application_Start in separate libraries.
For example, simply put the following code in a class library:
[assembly: WebActivator.PreApplicationStartMethod(typeof(WebAppInitializer), "Start")]
namespace FooBar
{
public static class WebAppInitializer
{
public static void Start()
{
// PROCESS ON APPLICATION START EVENT
}
}
}
and then referencing the class library in your ASP.NET application is all it takes.
You could also use this handy WebActivator to perform dependency injection into your HttpModules and self register them without the need to add them to web.config. Phil Haack wrote a nice blog post on this topic if you are interested.
Related
I have a class / service in my Blazor MAUI application that regularly manipulates the data that is stored within it. There is an internal schedular on a fixed interval that regenerates the value.
I have a Blazor component that reads the value from this service. When the value changes in my service, I would like my Blazor component to reflect that change.
Just to keep it simple, lets take the following:
public class EmployeeService {
public int NumberOfEmployees { get; private set; }
public EmployeeService() {
// Logic to initialize a fixed scheduled for function
// RecalculateNumberOfEmployees();
}
private async void RecalculateNumberOfEmployees() {
numberOfEmployees += 1;
}
}
#path "/employees"
#inject EmployeeService Service
Number of employees: #Service.NumberOfEmployees
#code {
}
I found a recommendation here that uses a timer to invoke StateHasChanged() but I really, really don't like that approach. It seems like it is a waste of resources and an anti-pattern.
My next step is to make EmployeeService accept EventCallback from the Blazor component and store that in a list. This would allow any component to listen for changes in the EmployeeService class. When a component is unmounted, it will delete the callback.
Something like:
EmployeeService.cs
public List<EventCallback> listeners { get; private set; } = new List<EventCallback>();
public async void RegisterCallback(EventCallback callback) {
listeners.ForEach(...notify listeners);
}
public async void DeregisterCallback(EventCallback callback) {
listeners.Remove ... etc
}
Employees.razor
...
#code {
// register / deregister callback and listen for changes, invoke StateHasChanged()
}
Before I go down this route, are there any better design patterns that I could use for future components that would be better suited for this purpose? I feel like this is something that should already be baked into the framework but haven't seen anything that addresses it.
You could use an event Action:
EmployeeService.cs
public class EmployeeService
{
public int NumberOfEmployees { get; private set; }
public EmployeeService() {
// Logic to initialize a fixed scheduled for function
// RecalculateNumberOfEmployees();
}
private async void RecalculateNumberOfEmployees() {
numberOfEmployees += 1;
NotifyStateChanged();
}
public event Action OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
Employees.razor
#inject EmployeeService EmployeeService
#implements IDisposable
Number of employees: #EmployeeService.NumberOfEmployees
#code {
protected override void OnInitialized()
{
EmployeeService.OnChange += OnChangeHandler;
}
public void Dispose()
{
EmployeeService.OnChange -= OnChangeHandler;
}
private async void OnChangeHandler()
{
await InvokeAsync(StateHasChanged);
}
}
Another possibility is to use the Event Aggregator pattern. Take a look at this library:
https://github.com/mikoskinen/Blazor.EventAggregator
I'm creating an ASP.net Core application with onion architecture.I want to raise some events in Business Logic layer and subscribe to these events from infrastructure layer.(layers from inner to outer: Domain - Contracts - Business Logic - Infrastructure - API)
one of my BL classes and event implementation:
public class LiveStreamBusinessLogic : ILiveStreamBusinessLogic
{
public event ILiveStreamBusinessLogic.LiveStreamEventHandler LiveStreamEventOccured;
public async Task<IBusinessLogicResult<PagedList<LiveStreamForShowDto>>> GetAllLiveStreamAsync(LiveStreamParameters liveStreamParameters)
{
// some logic
OnDomainEventOccured();
return new BusinessLogicResult<PagedList<LiveStreamForShowDto>>
{Success = true, Result = livesListForTransferPaged};
}
protected virtual void OnDomainEventOccured()
{
LiveStreamEventOccured?.Invoke(this, EventArgs.Empty);
}
}
also i'm using DI for creating upper class with this interface :
public interface ILiveStreamBusinessLogic
{
public delegate void LiveStreamEventHandler(object sender, EventArgs args);
public event LiveStreamEventHandler LiveStreamEventOccured;
Task<IBusinessLogicResult<PagedList<LiveStreamForShowDto>>> GetAllLiveStreamAsync(LiveStreamParameters liveStreamParameters);
}
and this class will instantiated through StartUp class:
services.AddScoped<ILiveStreamBusinessLogic, LiveStreamBusinessLogic>();
and my subscriber is :
public class ElasticLogger
{
private readonly ILoggerManager _loggerManager;
private readonly ILiveStreamBusinessLogic _liveStreamBusinessLogic;
public ElasticLogger(ILoggerManager loggerManager, ILiveStreamBusinessLogic liveStreamBusinessLogic)
{
_loggerManager = loggerManager;
_liveStreamBusinessLogic = liveStreamBusinessLogic;
Subscribe();
}
private void Subscribe()
{
_liveStreamBusinessLogic.LiveStreamEventOccured += OnDomainEventOccured;
}
private void OnDomainEventOccured(object sender, EventArgs e)
{
_loggerManager.LogInfo(Serialize(e).ToString());
}
}
and StartUp :
services.AddScoped<ElasticLogger>();
the problem is event will raise correctly but the handler does not execute. I guess there is a problem with the procedure of instantiating my classes in startup but have no idea how to solve it? any solution or even better pattern for this problem?
By looking at your example codes here, I cannot see that you are creating an instance of the ElasticLogger. That means no ElasticLogger is created, therefore it couldn't Subscribe.
You can check if my theory is correct or not, by putting a breakpoint in the constructor of ElasticLogger. If you never hit the breakpoint, then I'm right.
I suggest you to refactor ElasticLogger, don't call Subscribe from the constructor. But do like this:
public class ElasticLogger
{
private readonly ILoggerManager _loggerManager;
private readonly ILiveStreamBusinessLogic _liveStreamBusinessLogic;
public ElasticLogger(ILoggerManager loggerManager, ILiveStreamBusinessLogic liveStreamBusinessLogic)
{
_loggerManager = loggerManager;
_liveStreamBusinessLogic = liveStreamBusinessLogic;
}
public void Subscribe()
{
_liveStreamBusinessLogic.LiveStreamEventOccured += OnDomainEventOccured;
}
private void OnDomainEventOccured(object sender, EventArgs e)
{
_loggerManager.LogInfo(Serialize(e).ToString());
}
}
But, make sure you call it externally, after your application starts, call it like: elasticLogger.Subscribe() externally. Then your event should be handled.
I have a a completed (and broken) C# app below that generates a stack overflow exception. If you review the source code, you'll see why there's a stack overflow exception, so I'm not really looking at diagnosing WHY it happens, I want to know what the best way of handling it is.
1) All references to unity are encapsulated inside a Class named Registry so I can upgrade without difficulty. I don't want unitycontainer littering other classes where possible. In theory, I should be able to upgrade to 5 if/when it comes out, or even swap it out with ninject or other DI framework if I were to have a drastic change of disposition.
2) I want the Registry to be controlled by the unity container so that it can be used in the constructors for the container controlled classes. (eg FirstSingleInstance)
3) Both IRegistry and Registry inherit from IDisposable because I assume it's good practice to dispose the unity containers.
4) Registry constructs the Unity Container in it's own constructor, so I assume I should also dispose the unity container when registry.dispose is called.
5) all other classes that are controlled by Registry are expected to be single instance classes, so I register them with a ContainerControlledLifetimeManager. I expect those instances will be disposed when the container gets disposed.
What is the best practice for dealing with this situation?
a) do not call dispose on Registry -- let it live for the life of the process thread?
b) Don't try to have Registry (and by extension, UnityContainer) controlled by the unity container. That way calling dispose on Registry won't cause a stackoverflow exception. How I would then have unity construct the FirstSingleInstance class is something I'd have to review.
d) other?
Here's the app that I wrote that has all the relevant pieces
using System;
using Microsoft.Practices.Unity;
namespace DIProblem.Console
{
class Program
{
static void Main(string[] args)
{
IRegistry registry = CreateRegistry();
IFirstSingleInstance theInstance = registry.Resolve<IFirstSingleInstance>();
theInstance.DoThis();
registry.Dispose(); // stack overflow here because of infinite dispose loop
}
static IRegistry CreateRegistry() => new Registry();
}
public class FirstSingleInstance : IFirstSingleInstance
{
private IRegistry _registry;
public FirstSingleInstance(IRegistry reg)
{
_registry = reg;
}
public void DoThis()
{
System.Console.WriteLine("This Was Done.");
_registry.Resolve<ISecondSingleInstance>().DoThisToo();
}
}
public class SecondSingleInstance : ISecondSingleInstance
{
private IRegistry _registry;
public SecondSingleInstance(IRegistry reg)
{
_registry = reg;
}
public void DoThisToo()
{
System.Console.WriteLine("This Was Done too.");
}
}
public interface ISecondSingleInstance
{
void DoThisToo();
}
public interface IFirstSingleInstance
{
void DoThis();
}
public class Registry : IRegistry, IDisposable
{
public Registry()
{
_container = new UnityContainer();
RegisterInstance<IFirstSingleInstance, FirstSingleInstance>();
RegisterInstance<ISecondSingleInstance, SecondSingleInstance>();
_container.RegisterInstance<IRegistry>(this);
}
private UnityContainer _container;
public void RegisterInstance<T1, T2>() where T2 : class, T1 => _container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
public T Resolve<T>() => _container.Resolve<T>();
public void Dispose()
{
Dispose(true);
System.GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
_container?.Dispose();
_container = null;
}
}
public interface IRegistry : IDisposable
{
T Resolve<T>();
void RegisterInstance<T1, T2>() where T2 : class, T1;
}
}
Thank you for helping out in whatever way seems reasonable.
The following code refrains from using the Service Locator anti-pattern and instead relies solely on Constructor Injection as pattern for applying Inversion of Control. The result is a simpler, more maintainable and more testable application that doesn't cause any stackoverflow exceptions.
class Program
{
static void Main(string[] args)
{
using (var container = Registry.BuildContainer())
{
var theInstance = registry.Resolve<IFirstSingleInstance>();
theInstance.DoThis();
}
}
}
public static class Registry
{
public static UnityContainer BuildContainer()
{
var container = new UnityContainer();
container.RegisterType<IFirstSingleInstance, FirstSingleInstance>(Singleton);
container.RegisterType<ISecondSingleInstance, SecondSingleInstance>(Singleton);
return container;
}
private static ContainerControlledLifetimeManager Singleton =>
new ContainerControlledLifetimeManager();
}
public interface ISecondSingleInstance
{
void DoThisToo();
}
public interface IFirstSingleInstance
{
void DoThis();
}
public class FirstSingleInstance : IFirstSingleInstance
{
private ISecondSingleInstance _second;
public FirstSingleInstance(ISecondSingleInstance second)
{
_second = second;
}
public void DoThis()
{
System.Console.WriteLine("This Was Done.");
_second.DoThisToo();
}
}
public class SecondSingleInstance : ISecondSingleInstance
{
public SecondSingleInstance(/* other dependencies here */)
{
}
public void DoThisToo()
{
System.Console.WriteLine("This Was Done too.");
}
}
We're using private Nuget repository for serving packages in intranet environment. Is it possible to track what packages are downloaded to create basic statistics? For example which packages were downloaded the most, etc.
Presumably you have an ASP.NET application which uses the NuGet.Server package.
Then it would be quite easy to add some logging. You can decorate the PackageService:
public class MyPackageService : IPackageService
{
public MyPackageService(PackageService packageService)
{
_PackageService = packageService;
}
private readonly PackageService _PackageService;
public void CreatePackage(HttpContextBase context)
{
_PackageService.CreatePackage(context);
}
public void DeletePackage(HttpContextBase context)
{
_PackageService.DeletePackage(context);
}
public void DownloadPackage(HttpContextBase context)
{
// LOG HERE
Log(context);
_PackageService.DownloadPackage(context);
}
public void PublishPackage(HttpContextBase context)
{
_PackageService.PublishPackage(context);
}
}
and then change Routes.cs to rebind to MyPackageService.
public static class NuGetRoutes {
public static void Start() {
NinjectBootstrapper.Kernel.Rebind<IPackageService>().To<MyPackageService>();
MapRoutes(RouteTable.Routes);
}
//...
}
I have an application which resides in the system tray, and instead of the standard 'polling' method (check the server at X sec interval for updates) I wish to use a push notification system. So when there's an update, all clients will receive a message and they will do their task. The webserver will be Debian with Apache and PHP.
My target platform is .NET 3.5, so how would this be done? The Observer Design Pattern will not work (due to it's being .NET 4.0 or higher).
You have to create two interfaces and their derived concrete classes. Your service will create IObservable, IObserver and ApplicationErrorState.
Your client will create class and will derive ErrorMessageSync from IObserver.
Here is my example which displays errors and is created with .Net 3.5.
P.S. You can also use delegates
/// It will store observers and will push the message
public interface IErrorObservable
{
void Attach(IErrorObserver observer);
void Detach(IErrorObserver observer);
void Notify();
}
public interface IErrorObserver
{
void Update(string message);
}
///It is concrete class to push message
public sealed class ApplicationErrorState : IErrorObservable
{
private List<IErrorObserver> _observers = new List<IErrorObserver>();
///constructor
public ApplicationErrorState()
{
}
public void Attach(IErrorObserver observer)
{
_observers.Add(observer);
}
public void Detach(IErrorObserver observer)
{
_observers.Remove(observer);
}
public void Notify()
{
foreach (IErrorObserver observer in _observers)
{
observer.Update(/*Logic*/);
}
}
public void SetError()
{
Notify();
}
///COncrete subject
private class ErrorMessageSync : IErrorObserver
{
private MyClass _parent;
public ErrorMessageSync(MyClass parent)
{
_parent = parent;
}
public void Update(string message)
{
//This work will be done
}
}
This is UML for this approach.