Best way to notify observers in MVC? - model-view-controller

Say you have 5 or 6 variables in the model which a certain View is interested in, do you write different functions for each, such as
int a;
int b;
int c;
void setA( newA ) {
a = newA;
notifyAObservers();
}
void setB( newB ) {
b = newB;
notifyBObservers();
}
void setC( newC ) {
b = newC;
notifyCObservers();
}
Or do you just have one notify method and waste a little bit of CPU time
i.e. instead of notifyAObservers and notifyBObservers, you just have notifyObservers

I believe the traditional approach is to notify all observers, and let them handle it. This is because you don't know which observers are observing which variable(s) - you just know that they want to be notified when something changes. However, if you do know what observers are observing which variables, and performance is critical, then you might be able to do something like what you have.
In the traditional Observer pattern, the Observers implement an update() method that is called by the controller when a change happens. The Observables (the data model) would have a notifyObservers() method that iterates over the Observers and calls their update() method. Then, the Observers get whatever they need and the view updates.
Any time I have implemented the Observer pattern, however, I simply keep a list of observers and notify them all. That way, I only have one list of observers and the rest of the class as well as the different observers can all change without me making any changes to the observable class notification.

EDIT: I wrote my answer a few years ago. After reading it just now, I felt I needed to update it.
I believe the best approach is to notify all observers and let the views decide if they need to update themselves..
Each view will be able to verify the state of the model and act accordingly.
Additionally, the "args" could be used as a flag to indicate what has changed (the view may not wish to update itself for every little change).
That way, the model REALLY does not know how and what the view is displaying, they are decoupled.
A first implementation would look like this:
public class MyModelV1 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
notifyObservers();
}
public int getValue() {
return value;
}
}
public class MyViewV1 implements Observer {
public void update(Observable o, Object arg) {
if (o instanceof MyModelV1) {
System.out.println(((MyModelV1) o).getValue());
}
}
}
The view simply checks the type of the observable received.
However, if the model has many attributes and triggers the view for many different scenarios, this simple check may refresh the view too often.
Another approach would be the following:
public class MyModelV2 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
notifyObservers("value");
}
public int getValue() {
return value;
}
}
public class MyViewV2 implements Observer {
public void update(Observable o, Object arg) {
if (o instanceof MyModelV2 && "value".equals(arg)) {
System.out.println(((MyModelV2) o).getValue());
}
}
}
Here, the notification passes a qualifier, which lets the view decide more precisely when to refresh itself.
The view still needs to check and cast the Model, because there is no garantee that the arg "value" isn't notified by another model (and the cast would fail at runtime).
My personal favorite is something along those lines:
public class MyModelV3 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
Notification.MY_MODEL_VALUE_UPDATED.notifyObserver(this);
}
public int getValue() {
return value;
}
}
public class MyViewV3 implements Observer {
public void update(Observable o, Object arg) {
if (Notification.MY_MODEL_VALUE_UPDATED.equals(arg)) {
MyModelV3 model = Notification.MY_MODEL_VALUE_UPDATED.getModel(o);
System.out.println(model.getValue());
}
}
}
public class Notification<T extends Observable> {
public static final Notification<MyModelV3> MY_MODEL_VALUE_UPDATED = new Notification<MyModelV3>();
private Notification() {
}
public T getModel(Observable o) {
return (T) o;
}
public void notifyObserver(T observable){
observable.notifyObservers(this);
}
}
Here, the notification sends a strongly typed qualifier, which is bound to the Model.
The view is able to use the notification to retrieve a strongly typed model (instead of casting).
This is somewhere between an observer and an event bus..

Related

How and Where to tell if a ViewComponent has been invoked x times in a view?

I have a ViewComponent that I need to invoke twice only! How and where can I tell the invokations count?
Currently I can use a session but I dislike using session in mvc apps! How may I achieve this?
namespace Partials.Components
{
public class MyComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
Session["invoked"]=(int)Session["invoked"]+1;
var model = new{
Website="Stack Overflow",
Url="www.http://stackoverflow.com"
};
return View("_MyComponent ", model);
}
}
}
and in my view
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Session["invoked"]</span> times</span>
You can use TempData. It persists only until the next request.
TempData["invoked"]=(int)TempData["invoked"]+1;
View:
<span>Invoked ViewComponent <span>#TempData["invoked"]</span> times</span>
Note: TempData uses session under the covers.
You can use HttpContext.Items which has the advantage of not using the session. These items are stored and shared per request, which would also fit your objective.
In your viewComponent you can add/retrieve an item as in this.Context.Items["MyComponentInvocationCount"]. Whenever the count is greater than 2 you can just return an empty content with return Content(String.Empty).
You can combine that with an extension method so you can get the count from outside that class:
[ViewComponent(Name = "MyComponent")]
public class MyViewComponent : ViewComponent
{
internal static readonly string ContextItemName = "InvocationCount";
public IViewComponentResult Invoke()
{
this.InvocationCount = this.InvocationCount + 1;
if (this.InvocationCount > 2) return Content(String.Empty);
//return your content here
return Content("Can be invoked");
}
private int InvocationCount
{
get
{
return this.Context.InvocationCount();
}
set
{
this.Context.Items[ContextItemName] = value;
}
}
}
public static class MyViewComponentExtensions
{
public static int InvocationCount(this HttpContext context)
{
var count = context.Items[MyViewComponent.ContextItemName];
return count == null ? 0 : (int)count;
}
}
Then you could use it in a view as follows:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount()</span> times</span>
If you add the above lines 3 times in a view, you will see that the third one does not add any content.
EDIT - Using ViewComponentInvoker
I have been exploring how to implement this feature adding a custom ViewComponentInvoker.
I started by adding a new attribute that can be used to decorate ViewComponents so they are limited to a certain number of invocations per request:
public class PerRequestInvocationLimitAttribute: Attribute
{
public int PerRequestInvocationLimit { get; set; }
}
You would then create your view component as usual, the only change being adding this attribute:
[PerRequestInvocationLimit(PerRequestInvocationLimit = 2)]
public class MyViewComponent : ViewComponent
{
//implementation of view component
}
We can then create a custom IViewComponentInvoker that decorates the DefaultViewComponentInvoker.
This custom view component invoker will keep track of the number of
times a view component has been invoked in the current request.
When a view component that has the new attribute is invoked, it will only
really invoke it if the number of invocations is below the limit.
Implementing this view component invoker looks like:
public class LimitedPerRequestViewComponentInvoker : IViewComponentInvoker
{
private readonly IViewComponentInvoker _defaultViewComponentInvoker;
public LimitedPerRequestViewComponentInvoker(IViewComponentInvoker defaultViewComponentInvoker)
{
this._defaultViewComponentInvoker = defaultViewComponentInvoker;
}
public void Invoke(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return;
this._defaultViewComponentInvoker.Invoke(context);
}
public Task InvokeAsync(ViewComponentContext context)
{
if (!CanInvokeViewComponent(context)) return Task.WhenAll();
return this._defaultViewComponentInvoker.InvokeAsync(context);
}
private bool CanInvokeViewComponent(ViewComponentContext context)
{
// 1. Increase invocation count
var increasedCount = context.ViewContext.HttpContext.IncreaseInvocationCount(
context.ViewComponentDescriptor.ShortName);
// 2. check if there is any limit for this viewComponent, if over the limit then return false
var limitAttribute = context.ViewComponentDescriptor.Type
.GetCustomAttributes(true)
.OfType<PerRequestInvocationLimitAttribute>()
.FirstOrDefault();
if (limitAttribute != null && limitAttribute.PerRequestInvocationLimit < increasedCount)
{
return false;
}
// 3. There is no limit set or the limit has not been reached yet
return true;
}
}
It uses some extension methods to set/get the invocation count from HttpContext.Items (That you could also use in your view to get the number of times a view component was invoked)
public static class ViewComponentExtensions
{
public static int InvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.Items[GetHttpContextItemsName(viewComponentName)];
return count == null ? 0 : (int)count;
}
internal static int IncreaseInvocationCount(this HttpContext context, string viewComponentName)
{
var count = context.InvocationCount(viewComponentName);
context.Items[GetHttpContextItemsName(viewComponentName)] = ++count;
return count;
}
private static string GetHttpContextItemsName(string viewComponentName)
{
return string.Format("InvocationCount-{0}", viewComponentName);
}
}
The final piece is to create a new IViewComponentInvokerFactory replacing the default one, so it creates an instance of the new custom view component invoker instead of the default one. You also need to register it on Startup.cs:
public class MyViewComponentInvokerFactory : IViewComponentInvokerFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly ITypeActivatorCache _typeActivatorCache;
private readonly IViewComponentActivator _viewComponentActivator;
public MyViewComponentInvokerFactory(IServiceProvider serviceProvider, ITypeActivatorCache typeActivatorCache, IViewComponentActivator viewComponentActivator)
{
_serviceProvider = serviceProvider;
_typeActivatorCache = typeActivatorCache;
_viewComponentActivator = viewComponentActivator;
}
public IViewComponentInvoker CreateInstance(ViewComponentDescriptor viewComponentDescriptor, object[] args)
{
return new LimitedPerRequestViewComponentInvoker(
new DefaultViewComponentInvoker(_serviceProvider, _typeActivatorCache, _viewComponentActivator));
}
}
//Configure the ViewComponentInvokerFactory in Startup.ConfigureServices
services.AddTransient<IViewComponentInvokerFactory, MyViewComponentInvokerFactory>();
With all these pieces in place, you can use your view component 3 times and you will see how it will be rendered only twice:
#Component.Invoke("MyComponent")
<span>Invoked ViewComponent <span>#Context.InvocationCount("MyComponent")</span> times</span>
I prefer this solution for a few reasons:
It is based on the hooks provided by the new mvc framework.
Does not need changes to your view component, other than adding the attribute that sets the invocation limit.
It works when invoking view component asynchronously.

Validating deserialised object with Postsharp Contracts

[This is kind of an obvious question but I couldn't find anything about it - if someone could reference me, it'll be grand.]
In a WebAPI project:
public class MyObject
{
[PostSharp.Patterns.Contract.Required]
public string Name {get;set;}
}
public class MyController : ApiController
{
public HttpResponseMessage Post([FromBody]MyObject obj)
{
/// ...
}
}
During compilation, I guess PostSharp's validations put themselves in the setter of the property, so when obj is deserialised from the request's body, its fields aren't validated.
So, what's the best/clean way to validate that object?
Cheers
There is currently no clean way to achieve such validation as it is presumed that once-serialized object is already valid.
In order to force the validation logic, one would need to use ISerializationCallback interface's OnDeserialized method, go through properties and forcibly set them to their current value in order to enforce validation.
This can be done by a PostSharp aspect, but it would be certainly non-trivial. Other possibility is to use reflection/expression trees to achieve the same.
If you think that this would be a nice feature of PostSharp, you can vote PostSharp's UserVoice page.
As Daniel Balas wrote, there's no simple solution to trigger PostSharp's validations after deserializing an object, except implementing OnDeserialized method of ISerializationCallback interface. So I post an Aspect I wrote that deep copies public properties of objects one by one through reflection, and hence activating the validations in the setters.
[Serializable]
public sealed class ArgsValidationAspect : MethodInterceptionAspect
{
public override bool CompileTimeValidate(MethodBase method)
{
if (!method.GetParameters().Any(p => p.ParameterType.IsClass))
{
Message.Write(method, SeverityType.Error, "MY001", "Cannot apply HttpObjectValidationAspect to method '{0}'.", method);
return false;
}
return true;
}
public override void OnInvoke(MethodInterceptionArgs args)
{
foreach (var arg in args.Arguments)
{
try
{
RecursiveCopyInstance(arg);
}
catch (Exception e)
{
throw e.InnerException ?? e;
}
}
base.OnInvoke(args);
}
private static object RecursiveCopyInstance(object origin)
{
var type = origin.GetType();
var instance = Activator.CreateInstance(type);
foreach (var prop in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
var val = prop.GetValue(origin);
if (val != null && !prop.PropertyType.IsPrimitive && !prop.PropertyType.Equals(typeof(string)))
{
val = RecursiveCopyInstance(val);
}
prop.SetValue(instance, val);
}
return instance;
}
}

How to pass Data to different Views in MVVM Light?

I am kinda unclear on how to pass data to other views. I gathered there are 3 ways to do this but I not sure how to do 2 of them.
Send data through messenger(not sure if you can send objects otherwise I can see thing getting pretty messy if you have to send like 10 pieces of data or something like that along).
Somehow pass the data through the constructor of the new view model. I say "somehow" as I am unclear how to do that when using an IOC container(in this case the built in one).
Passing the data through a parameter. I seen a couple of tutorials that show you how to do navigation for the windows phone but none really talk about parameter passing. I am guessing this would still be an option.
From what I heard is that Option 1 is sort of the old way of doing it. Option 2 seems to be a newer way and better way to do it but I cannot find any examples on people showing how to do it.
I don't know how to do it because the Ioc should be creating the instance of the view so how do you pass in data into it when that data does not exist?
The two main ways I do this is:
1)Use the messenger:
Sender class:
public class TrafficLight
{
public string Color{get;set;}
public TimeSpand Duration{get;set;}
}
public class TrafficLightService
{
public void SendLight(TrafficLight light)
{
Messenger.Default.Send(light);
}
}
Receiver:
public class MyViewModel
{
public MyViewModel()
{
Messenger.Default.Register<TrafficLight>(DoSomethingWithTrafficLight);
}
private void DoSomethingWithTrafficLight(TrafficLight light)
{
}
}
What happens here is that the source object is using the Messenger as an event broker. Object A doesn't need to know about object B, they just both need to know about the messenger.
2)
Just use dependency injection:
public class TrafficLight
{
public string Color{get;set;}
public TimeSpand Duration{get;set;}
}
public class LightEventArgs:EventArgs
{
public LightEventArgs(TrafficLight light)
{
_light=light;
}
public TrafficLight Light{get{return _light;}}
}
public interface ITrafficLightService
{
void SendLight(TrafficLight light);
public event EventHandler<LightEventArgs> TrafficLightSet;
}
public class TrafficLightService
{
public void SendLight(TrafficLight light)
{
Messenger.Default.Send(light);
}
public event EventHandler<LightEventArgs> TrafficLightSet;
}
public class TrafficLightSenderViewModel
{
public TrafficLightSenderViewModel(ITrafficLightService trafficLightService)
{
_trafficLightService=trafficLightService;
_trafficLightService.Send(new TrafficLight{Color="Red"});
}
}
public class TrafficLightReceiverViewModel
{
public TrafficLightReceiverViewModel(ITrafficLightService trafficLightService)
{
_trafficLightService=trafficLightService;
_trafficLightService.TrafficLightSet+= TrafficLightNotification;
}
private void TrafficLightNotification(TrafficLightEventArgs args)
{
DoSomethingWithTheLight(args.Light);
}
}
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<ITrafficLightService, Design.TrafficLightService>();
}
else
{
SimpleIoc.Default.Register<ITrafficLightService, TrafficLightService>();
}
SimpleIoc.Default.Register<TrafficLightSenderViewModel>();
SimpleIoc.Default.Register<TrafficLightReceiverViewModel>();
}
public MainViewModel Sender
{
get { return SimpleIoc.Default.GetInstance<TrafficLightSenderViewModel>(); }
}
public MainViewModel Receiver
{
get { return SimpleIoc.Default.GetInstance<TrafficLightReceiverViewModel>(); }
}
}
This is a bigger example and more complex.
Lets walk through this step by step:
In MVVM Light we use the ViewModelLocator for 2 things: 1)To register all our viewmodels and services.
Provide a way to allow the View to get a viewmodel in XAML
When we try to resolve a ViewModel
SimpleIoc.Default.GetInstance<TrafficLightReceiverViewModel>();
SimpleIoc looks at whether the viewmodel has any dependencies. In our case we do, we need an ITrafficLightService for both our viewmodels. What happens is that SimpleIoc sees if it can resolve that class and, in the process, checks to see if ITrafficLightService has any dependencies that need resolving as well. If SimpleIoc can resolve the chain of dependencies required to instantiate your viewmodel it does so and then hands back a fully built object.

How to structure many event-like methods?

The central object of a system I'm developing is getting a bit too unwieldy. The problem is that it can be acted upon in so many different ways. You can:
Cancel it
Deny it
Discard it
Sell it
Split it
Expire it
... and plenty more.
I'm considering factorizing those event-like methods away from the class and make it a bit more generic, like a Command pattern. But most of the methods have different parameters, so using a solution like Run() or Execute() could be a problem perhaps?
Any ideas how to structure this, to make it flexible and simple to add new commands, or actions or what you would like to call them? (I wouldn't call them real events since there are no listeners.)
Can you pass the required parameters for your commands in their constructor ? That way, you can have a parameter-less command.
class SellItCommand : ICommand {
private decimal price;
SellItCommand(decimal price) {
this.price = price;
}
void Execute() {
// Do whatever needs to be done with in the sell command using this.price
}
}
Encapsulate the parameters, as a single parameter:
public class SellCommand: Command {
Product OwnerProduct;
ProductCommand (AOwnerProduct)
{
this.OwnerProduct = AOwnerProduct;
}
public override void Execute(KeyValueArray Parameters)
{
double Price = (double)Parameters.ValueofKey("price");
// do something else
}
}
public class BuyCommand: Command {
Product OwnerProduct;
ProductCommand (AOwnerProduct)
{
this.OwnerProduct = AOwnerProduct;
}
public override void Execute(KeyValueArray Parameters)
{
double Cost = (double)Parameters.ValueofKey("cost");
// do something else
}
}
public class Product {
public void AnyMethod()
{
KeyValueArray Parameters = new KeyValueArray Parameters();
KeyValueArray.Add("price", "12.5");
}
}
Its sort of pseudocode, you may like to use the collection libraries that match your programming framework.

Validation in a Domain Driven Design

How do you deal with validation on complex aggregates in a domain driven design? Are you consolidating your business rules/validation logic?
I understand argument validation and I understand property validation which can be attached to the models themselves and do things like check that an email address or zipcode is valid or that a first name has a minimum and maximum length.
But what about complex validation that involves multiple models? Where do you typically place these rules & methods within your architecture? And what patterns if any do you use to implement them?
Instead of relying on IsValid(xx) calls all over your application, consider taking some advice from Greg Young:
Don't ever let your entities get into
an invalid state.
What this basically means is that you transition from thinking of entities as pure data containers and more about objects with behaviors.
Consider the example of a person's address:
person.Address = "123 my street";
person.City = "Houston";
person.State = "TX";
person.Zip = 12345;
Between any of those calls your entity is invalid (because you would have properties that don't agree with each other. Now consider this:
person.ChangeAddress(.......);
all of the calls relating to the behavior of changing an address are now an atomic unit. Your entity is never invalid here.
If you take this idea of modeling behaviors rather than state, then you can reach a model that doesn't allow invalid entities.
For a good discussion on this, check out this infoq interview: http://www.infoq.com/interviews/greg-young-ddd
I like Jimmy Bogard's solution to this problem. He has a post on his blog titled "Entity validation with visitors and extension methods" in which he presents a very elegant approach to entity validation that suggest the implementation of a separate class to store validation code.
public interface IValidator<T>
{
bool IsValid(T entity);
IEnumerable<string> BrokenRules(T entity);
}
public class OrderPersistenceValidator : IValidator<Order>
{
public bool IsValid(Order entity)
{
return BrokenRules(entity).Count() == 0;
}
public IEnumerable<string> BrokenRules(Order entity)
{
if (entity.Id < 0)
yield return "Id cannot be less than 0.";
if (string.IsNullOrEmpty(entity.Customer))
yield return "Must include a customer.";
yield break;
}
}
I usualy use a specification class,
it provides a method (this is C# but you can translate it in any language) :
bool IsVerifiedBy(TEntity candidate)
This method performs a complete check of the candidate and its relations.
You can use arguments in the specification class to make it parametrized, like a check level...
You can also add a method to know why the candidate did not verify the specification :
IEnumerable<string> BrokenRules(TEntity canditate)
You can simply decide to implement the first method like this :
bool IsVerifiedBy(TEntity candidate)
{
return BrokenRules(candidate).IsEmpty();
}
For broken rules, I usualy write an iterator :
IEnumerable<string> BrokenRules(TEntity candidate)
{
if (someComplexCondition)
yield return "Message describing cleary what is wrong...";
if (someOtherCondition)
yield return
string.Format("The amount should not be {0} when the state is {1}",
amount, state);
}
For localization, you should use resources, and why not pass a culture to the BrokenRules method.
I place this classes in the model namespace with names that suggest their use.
Multiple model validation should be going through your aggregate root. If you have to validate across aggregate roots, you probably have a design flaw.
The way I do validation for aggregates is to return a response interface that tells me if validation pass/fail and any messages about why it failed.
You can validate all the sub-models on the aggregate root so they remain consistent.
// Command Response class to return from public methods that change your model
public interface ICommandResponse
{
CommandResult Result { get; }
IEnumerable<string> Messages { get; }
}
// The result options
public enum CommandResult
{
Success = 0,
Fail = 1
}
// My default implementation
public class CommandResponse : ICommandResponse
{
public CommandResponse(CommandResult result)
{
Result = result;
}
public CommandResponse(CommandResult result, params string[] messages) : this(result)
{
Messages = messages;
}
public CommandResponse(CommandResult result, IEnumerable<string> messages) : this(result)
{
Messages = messages;
}
public CommandResult Result { get; private set; }
public IEnumerable<string> Messages { get; private set; }
}
// usage
public class SomeAggregateRoot
{
public string SomeProperty { get; private set; }
public ICommandResponse ChangeSomeProperty(string newProperty)
{
if(newProperty == null)
{
return new CommandResponse(CommandResult.Fail, "Some property cannot be changed to null");
}
SomeProperty = newProperty;
return new CommandResponse(CommandResult.Success);
}
}
This questions a bit old now but in case anyone is interested here's how I implement validation in my service classes.
I have a private Validate method in each of my service classes that takes an entity instance and action being performed, if validation fails a custom exception is thrown with the details of the broken rules.
Example DocumentService with built in validation
public class DocumentService : IDocumentService
{
private IRepository<Document> _documentRepository;
public DocumentService(IRepository<Document> documentRepository)
{
_documentRepository = documentRepository;
}
public void Create(Document document)
{
Validate(document, Action.Create);
document.CreatedDate = DateTime.Now;
_documentRepository.Create(document);
}
public void Update(Document document)
{
Validate(document, Action.Update);
_documentRepository.Update(document);
}
public void Delete(int id)
{
Validate(_documentRepository.GetById(id), Action.Delete);
_documentRepository.Delete(id);
}
public IList<Document> GetAll()
{
return _documentRepository
.GetAll()
.OrderByDescending(x => x.PublishDate)
.ToList();
}
public int GetAllCount()
{
return _documentRepository
.GetAll()
.Count();
}
public Document GetById(int id)
{
return _documentRepository.GetById(id);
}
// validation
private void Validate(Document document, Action action)
{
var brokenRules = new List<string>();
if (action == Action.Create || action == Action.Update)
{
if (string.IsNullOrWhiteSpace(document.Title))
brokenRules.Add("Title is required");
if (document.PublishDate == null)
brokenRules.Add("Publish Date is required");
}
if (brokenRules.Any())
throw new EntityException(string.Join("\r\n", brokenRules));
}
private enum Action
{
Create,
Update,
Delete
}
}
I like this approach because it allows me to put all my core validation logic in one place which keeps things simple.

Resources