I'm developing a multi tenant n-tier web application using asp.net Mvc 5.
In my service layer I am defining custom events for every important action and raising these events once these actions are executed. For example
Public event EventHandler EntityCreated;
Public void Create(Entity item) {
Save(item);
......
EntityCreated(this, item);
}
I intend on hooking up business rules and notifications to these events. The main reason I want to use events is decoupling of the logic and easy plug-ability of more events handlers without modifying my service layer.
Question:
Does it make sense using events and delegates in asp.net?
Most examples I find online are for win forms or wpf. I get the advantage when it comes to multithreaded applications. Also the events are defined once per form and are active for the lifetime of the form.
But in my case the events will be per http request. So is it an overhead defining these events?
As others pointed out that pub/sub or event bus is one solution. Another solution is something like what you are trying to do here but make it more formal.
Let's take a specific example of creating a customer. You want to send a welcome email when a new customer is created in the application. The domain should only be concerned with creating the customer and saving it in the db and not all the other details such as sending emails. So you add a CustomerCreated event. These types of events are called Domain Event as opposed to user interface events such as button click etc.
When the CustomerCreated event is raised, it should be handled somewhere in the code so that it can do the needful. You can use an EventHandlerService as you mentioned (but this can soon becomes concerned with too many events) or use the pattern that Udi Dahan talks about. I have successfully used Udi's method with many DI Containers and the beauty of the pattern is that your classes remain SRP compliant. You just have to implement a particular interface and registration code at the application bootstrap time using reflection.
If you need further help with this topic, let me know and I can share with you the code snippets to make it work.
I have implemented Udi Dahan's implementation as pointed out by #Imran but with a few changes.
My Events are being raised in a Service Layer and for that using a Static Class dint seem right. Also have added support for async/await.
Also going down the Events & Delegates path did work out but it just felt like an overhead to register the events per request.
I have blogged my solution here http://www.teknorix.com/event-driven-programming-in-asp-net
Related
When should I be using an Event Handler versus an Event Aggregator?
In my code, I have two ViewModels that controlled by a parent ViewModel, I am trying to decide if I should just use an event handler to talk between them? Or use an Event Aggregator? It is going to just be simple method call, I don't require parameters to be passed between them.
The way I see it, the EventAggregator is usually the heavy gun used when you want to publish an event to the entire application and more specifically - when you don't know who exactly is listening.
In your scenario that's not really the case, you have 2 view models that want to communicate, but they both know each other. So there is no real reason you can't use events.
I'll just mention that if you want to keep it a little more loosely-coupled - make an interface for each of the viewmodels that exposes the event. This way each VM will use the other VM's Interface instead of a specific instance.
Here is a link with some good info (that is alive as of 5/2019)...
https://learn.microsoft.com/en-us/previous-versions/windows/apps/xx130639(v%3dwin.10) (Microsoft, Prism)
The "Making key decisions" section describes when to use it.
Events in .NET implement the publish-subscribe pattern. The publisher and subscriber lifetimes are coupled by object references to each other, and the subscriber type must have a reference to the publisher type.
Event aggregation is a design pattern that enables communication between classes that are inconvenient to link by object and type references. This mechanism allows publishers and subscribers to communicate without having a reference to each other. Therefore, .NET events should be used for communication between components that already have object reference relationships (such as a control and the page that contains it), with event aggregation being used for communication between loosely coupled components (such as two separate page view models in an app). For more info see Event aggregation.
I crudely see this as suggesting C# events are good for layers (UI listening to bus logic) or parent/child (an instrument listening to its contained devices) and event aggregation is good for siblings (e.g., sibling UI panels or device to device communication).
I am writing a websocket test application that will have a GUI to send various commands over the websocket. Rather than pack all the control code (message construction, formatting, control) into the callbacks for various controls, I am considering having each GUI element callback (e.g., onClick) send an event to a delegate that can handle it. That way the GUI would be separate from any control code. Is that a 'sane' design, or is there another 'best practice' to separate the two parts.
An example would be a TV Tuner control -- the user can enter a channel number via textbox, which will have no effect until they click the 'Tune' button. The onClick method could retrieve the channel number from the textbox, and send a doTune(channel) event to the delegate to make it happen.
Thoughts/advice welcome.
Thank you,
bp
This is indeed a sane design. I personally won't go for an event call, just a regular call to a static 'SocketCommands' class will do.
That is indeed a very sensible design - what you're doing is promoting a good seperation of concerns between the presentation layer (UI) and the business layer (transaction scripts, domain services etc).
So to answer your question, yes, it is a sane design :)
With regards to thoughts/advice, that would be a topic for programmers.stackexchange.com rather than here..
I am using EventAggregator in Prism, and I want the events persisted, which means when a client subscribes a certain event, the aggregator published the previous events that missed to the client. Is there a way to support this?
I know this sounds more like a message queue or something. But the system has already heavily coupled with EventAggregator thus I want this framework can allow me to selectively persist some events without too much modification.
The following article discusses a "store and forward" EventAggregator implementation which sounds like an excellent match for your scenario i.e. clients being able to catch up with events they may have missed:
http://www.ademiller.com/blogs/tech/2008/11/adding-store-and-forward-support-to-the-prism-eventaggregator/
I've been looking in to the Composite Application Library, and it's great, but I'm having trouble deciding when to use the EventAggregator... or rather - when NOT to use it.
Looking at the StockTraderRI example, I'm even more confused. They are using the EventAggregator in some cases, and "classic" events in other cases (in for example the IAccountPositionService interface).
I've already decided to use it for communication with a heavy work task, that should run on a background thread. In this case the EventAggregator offers marshalling of threads behind the scenes, so I don't have to worry much about that. Besides that I like the decoupling this approach offers.
So my question is: When I've started using the EventAggregator in my application, why not use it for all custom events?
This is a good question. In Composite WPF (Prism) there are 3 possible ways to communicate between parts of your app. One way is to use Commanding, which is used only to pass UI-triggered actions down the road to the actual code implementing that action. Another way is to use Shared Services, where multiple parts hold a reference to the same Service (Singleton) and they handle various events on that service in the classical way. For disconnected and asynchronous communication, as you already stated, the best way is to use the Event Aggregator (which follows closely Martin Fowler's pattern).
Now, when to and not to use it:
Use it when you need to communicate between modules. (for example, a Task module needs to be notified when a Task is created by any other module).
Use it when you have multiple possible receivers or sources of the same event. For example, you have a list of objects and you want to refresh it whenever an object of that type is saved or created. Instead of holding references to all open edit/create screens, you just subscribe to this specific event.
Don't use it when you only have to subscribe to normal events in the Model View Presenter area. For example, if your presenter listens to changes in the Model (for example the Model implements INotifyPropertyChanged) and your Presenter needs to react on such changes, it's better that your Presenter handles directly the PropertyChanged event of the Model instead of diverting such events through the Event Aggregator. So, if both the sender and receiver are in the same unit, there's no need to "broadcast" such events to the whole application.
I hope this answers your question.
First off, there's a bit of background to this issue available on my blog:
http://www.codebork.com/coding/2008/06/25/message-passing-a-plug-framework.html
http://www.codebork.com/coding/2008/07/31/message-passing-2.html
I'm aware that the descriptions aren't hugely clear, so I'll try to summarise what I'm attempting as best I can here. The application is a personal finance program. Further background on the framework itself is available at the end of this post.
There are a number of different types of plug-in that the framework can handle (e.g., accounts, export, reporting, etc.). However, I'm focussing on one particular class of plug-in, so-called data plug-ins, as it is this class that is causing me problems. I have one class of data plug-in for accounts, one for transactions, etc.
I'm midway through a vast re-factoring that has left me with the following architecture for data plug-ins:
The data plug-in object (implementing intialisation, installation and plug-in metadata) [implements IDataPlugin<FactoryType>]
The data object (such as an account) [implements, e.g., IAccount]
A factory to create instances of the data object [implements, e.g., IAccountFactory]
Previously the data object and the plug-in object were combined into one, but this meant that a new transaction plug-in had to be instantiated for each transaction recorded in the account which caused a number of problems. Unfortunately, that re-factoring has broken my message passing. The data object implements INotifyPropertyChanged, and so I've hit a new problem, and one that I'm not sure how to work around: the plug-in object is registering events with the message broker, but it's the data objects that actually fire the events. This means that the subscribing plug-in currently has to subscribe to each created account, transaction, etc.! This is clearly not scalable.
As far as I can tell at the moment I have two possible solutions:
Make the data plug-in object a go-between for the data-objects and message broker, possibly batching change notifications. I don't like this because it adds another layer of complexity to the messaging system that I feel I should be able to do without.
Junk the current event-based implementation and use something else that's more easily manageable (in-memory WCF?!).
So I guess I'm really asking:
How would you solve this problem?
What potential solutions do you think I've overlooked?
Is my approach even vaguely on-track/sensible?! :-)
As you will be able to tell from the dates of the blog posts, some variant of this problem has been taxing me for quite a long time now! As such, any and all responses will be greatly appreciated.
The background to the framework itself is as follows:
My plug-in framework consists of three main components: a plug-in broker, a preferences manager and a message broker. The plug-in broker does the bread-and-butter plug-in stuff: discovering and creating plug-ins. The preferences manager manages user preferences for the framework and individual plug-ins, such as which plug-ins are enabled, where data should be saved, etc. Communication is via publish/subscribe, with the message broker sitting in the middle, gathering all published message types and managing subscriptions. The publish/subscribe is currently implemented via the .NET INotifyPropertyChanged interface, which provides one event called PropertyChanged; the message broker builds a list of all plug-ins implementing INotifyPropertyChanged and subscribes other plug-ins this event. The purpose of the message passing is to allow the account and transaction plug-ins to notify the storage plug-ins that data has changed so that it may be saved.
Wow! Big question! :)
Correct me if I'm wrong. Your basic solution now is kind of an Observer pattern, where the data object (Account, etc) notifies about changes in their states. You think that the problem is that the subscribing plugin has to register in every object to be able to handle notifications.
That's not a problem per se, you can put the event control in the Domain Model, but I suggest you create a Service Layer and do this event notifications in this layer. That way just one object would be responsible for publishing notifications.
Martin Fowler have a series of Event Patterns in his blog. Check it out! Very good reading.
This is my understanding of your question: You have a plugin object that may have to listen for events on x data objects - you don't want to subscribe to the event on each data object though. I'm assuming that several plugins may want to listen to events on the same data object.
You could create a session type object. Each plugin listens for events on the session object. The data object no longer raises the event - it calls the session object to raise the event (one of the parameters would have to be the data object raising the event).
That means that your plugins only have to subscribe to one event, but they get the event from all data objects.
On the other hand, if only one plugin will ever listen to a data object at a time, why not just have the data object call the plugin directly?
It's early yet, but have you considered trying to use MEF instead of rolling your own?