How do you create a FubuMVC behavior that copies site configuration values to an output model? - fubumvc

I'm trying to figure out to create a behavior that will copy a boolean site configuration value to an output model.
This way I don't have to copy the bool in each action who's view requires it, but can simply add the behavior to the controller actions that need this value.
In some of the older versions of FubuMVC, I believe behaviors could modify the output model after it's left the controller. But I'm not sure how to do this in the more recent versions of FubuMVC (or I've forgotten).
Can anyone give me an example of or point me in the direction of the best practice for copying a site configuration value to an output model?

Let's say I had an output model called HomeViewModel that had a property called FooterText that I wanted loaded from settings object (let's say HomeSettings) that was retrieved from the container (i.e. StructureMap).
The Behavior
My behavior would look something like this:
public class HomeFooterBehavior : BasicBehavior
{
private readonly HomeSettings _settings;
private readonly IFubuRequest _request;
public HomeFooterBehavior(HomeSettings settings, IFubuRequest request)
: base(PartialBehavior.Executes)
{
_settings = settings;
_request = request;
}
protected override DoNext performInvoke()
{
SetupFooter();
return DoNext.Continue;
}
public void SetupFooter()
{
var viewModel = _request.Find<HomeViewModel>().First();
viewModel.HomeFooterText = _settings.FooterText;
}
}
This behavior takes in the HomeSettings object and the IFubuRequest object (both injected dependencies) and then gets the HomeViewModel (output model) from the request and then sets the HomeFooterText property on the output model based on the value from the settings object.
NOTE: I'm assuming that you've already got your HomeSettings object wired up in the container (for example, using the ISettingsProvider stuff built into FubuMVC). If you don't already have this, let me know and I can post some code on how to do that.
Wiring Up The Convention
To wire up the behavior, you'll need to define the convention through an IConfigurationAction, for example:
public class HomeFooterBehaviorConfiguration : IConfigurationAction
{
public void Configure(BehaviorGraph graph)
{
graph.Actions()
.Where(x => x.HasOutput &&
x.OutputType().Equals(typeof(HomeViewModel)))
.Each(x => x.AddAfter(Wrapper.For<HomeFooterBehavior>()));
}
}
This is a real dumb convention for demonstration purposes. In your project, you might make it a little more generic. For example, any output model that has an attribute on it, or implements a specific interface, etc. In fact, you might want to inspect all output models to see if they contain any properties that match a certain criteria (for example, all properties that end with "Settings" - like "FooterSettings" or something).
Don't be afraid to define wide sweeping conventions like this due to performance concerns since all this convention code runs at start-up time and not on every request.
Note the "AddAfter" call and the "Wrapper.For" call. That's the key in that it places your behavior after the controller action is executed, but before the view is rendered.
Now that you have your behavior and your convention defined, it's time to wire it up in your FubuRegistry.
Wiring Up Your Convention in your FubuRegistry
After the call to "Routes." in your FubuRegistry, add a line like this:
ApplyConvention<HomeFooterBehaviorConfiguration>();
Recompile and it should work.
Please let me know if you run into any problems.

Related

Xamarin + Prism: bubble property change events from hierarchical model / view model or ...?

I've been trying to find the correct approach for this problem I got, using Prism with Xamarin Forms:
I've a model class, Customer, that contains another class, Address as a property. In my view, I show fields from both objects. I would like to have a "save" button, that only gets enabled after you've made some changes to those models.
Now, the button is bound to a Command, with the corresponding CanSave() function, as is normal with DelegateCommands. I'm trying to find an approach where I can end up with a single IsDirty property on my view model, that gets to "true" after any changed to the underlying models.
The MVVM approach
First thing I thought was the "purist" mvvm approach. A "flat" view model, with properties for each visual element, implemented as a Prism BindableObject, where each getter/setter gets/sets values from/to the underlying model classes.
That failed though, since SetProperty<> has a ref parameter, where I can't use properties from my models.
The over-engineered approach [?]
Second thing I thought was that, if my inner models were observables themselves, I could listen for changes from all of them, throughout the tree. Which opens up a whole new world of issues. Do I register property change listeners in my View model ? Do I make inner models observables, and have the parents listen for change events on their children and propagate that ?
Won't that observable models approach quickly become event handler hell ?
The simplest thing
And last, the simplest thing possible. I have a flat observable ViewModel, that only reads/writes values to/from the actual inner hierarchical model upon read & save
What do you guys think ?
Maybe I didn't understand your question right, but I'm wondering why you limit yourself to such a small helper function like SetProperty. It has 4 Lines of code. All it does is checking for equality, setting a value and raising an event.
You could easily create another helper function like this.
MyBindableBase
protected virtual bool SetProperty<T>(Func<T> get, Action<T> set, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(get(), value)) return false;
set(value);
OnPropertyChanged(propertyName);
return true;
}
Model
class Model
{
public string Property { get; set; }
}
ViewModel
class ViewModel : BindableBase
{
private Model Model { get; set; }
public string Property
{
get { return Model.Property; }
set { SetProperty(() => Model.Property, x => Model.Property = x, value); }
}
}
I think you can shorten the usage, if you introduce some naming rules for the mapping and/or use reflections.
Well, in the end I went for option 3, the simplest thing I could do.
I was leaning towards returning properties from my model, which would be easy, and using the nullable [?.] syntax it would be null-safe too, but I found that at times I'll have to wrap the actual model properties with something that is more UI-friendly, exposing more/different properties than my actual DB model classes.
So, I went for that, until some other complexity forces me to change my mind again :)
Thanks a lot #Sven-Michael Stübe and #adminSoftDK for the help

How to access the value of a Property argument from nested activities?

I'm sure there's something I'm missing here, but a lot of Googling hasn't uncovered it for me. The situation is like this:
We created a custom workflow designer that allows end users to build workflow definitions from various custom activities we define (Review, Submit, Notify, etc). These definitions (Xaml) get saved off to a Db and used to create workflow instances for long running processes in our system. The users can set properties on each of them (e.g. Review has a property argument: AllowedRoles). The problem is, I'm not able to pass those properties on to nested activities.
For example:
Review has an internal activity 'WriteStatus' that needs access to the 'AllowedRoles' property on Review. If 'AllowedRoles' is defined as a Property, WriteStatus can't "see" it to assign it's value. I can change it from a Property to an InArgument, but then I'm not able to map values to and from the property in the designer (these properties should be part of the definition, and not associated with any specific context).
Has anyone faced this issue or have advice on how I could approach the problem differently?
Thanks in advance!
Royce
I was able to get around the property vs InOurArgument problem by converting the XAML activities to code. This allowed me to set the properties on activities in code, and then pass them to inner activities inline. There may be a better way, but it's working out well so far.
public sealed class Test : Activity
{
public string Stuff { get; set; } // CLR Property
public Test()
{
Implementation = () => new WriteLine {Text = Stuff};
}
}

Command class in Caliburn Micro

On my first project trying out Caliburn.Micro, I like a lot of the things :-)
One thing I miss (or havn't discovered yet) is how to separate the viewmodel and a command.
CM doesn't support ICommand, as it's way of doing things is superior. I'm sure it's true, so I would love a small push in the right direction to achieve this or perhaps discover a better way.
As I understand you have to put the "Execute" method and "CanExecute" property directly in the viewmodel, named to match the control in the view, to get the magic to work.
I would like to put the "Execute" and "CanExecute" in a different object that is property on the viewmodel and then CM would automatically bind to that object, using the control name and property names as usually.
Repost from the forum on Caliburn Micro, I didn't get any answers so I'm trying my luck here.
You should try to avoid invalidating the Law of Demeter. Therefore, on your view model you can have an execute method, and a CanExecute property (usually calculated), and these can call into the containing model where appropriate, e.g:
public void Save
{
// .. save logic
}
public bool CanSave
{
get
{
return this.model.CanSave ... and other logic etc.
}
}
You must remember to notify a change in the calculated property when the can save state changes, e.g:
public void CodeThatGetsRunWhenAPropertyOfTheModelChanges()
{
this.NotifyOfPropertyChanged(() => this.CanSave);
}
If you have e.g. a Button on your view with x:Name="Save", then Caliburn.Micro will automatically invoke your Save verb on the view model when the button is clicked, and will automatically enable and disable the button when the CanSave property value changes.
To avoid fat ViewModels you also need to avoid fat Views. Caliburn.Micro allows you to compose Views/ViewModels as described in Screens, Conductors and Composition.
The short version is, you can include a "DetailView" and "DetailViewModel" pair in a "MasterView"/"MasterViewModel" shell by defining a DetailViewModel-typed property in MasterViewModel and adding a ContentControl named after it in MasterView. Binding and actions work as usual, so you avoid both fat models/views and routing of commands.
Another option is to bind a MasterView element to a DetailViewModel property or action, by prepending the detail's property to the target's name. I can't find the specific URL yet, so the example is from memory.
Assuming you have the following classes:
public class MasterViewModel:Screen
{
public property DetailViewModel MyDetails{get;set;}
}
and
public class DetailViewModel:Screen
{
public property string SomeText{get;set;}
public void DoTheBoogie(){}
}
You can add a control in you MasterView named 'MyDetails_SomeText' to bind to the DetailViewModel.SomeText. You can also bind to DoTheBoogie the same way.
I prefer to create a separate View though, named DetailView and add a ContentControl named "MyDetails" in MasterView. This results in a cleaner and more modular design

Class design: file conversion logic and class design

This is pretty basic, but sort of a generic issue so I want to hear what people's thoughts are. I have a situation where I need to take an existing MSI file and update it with a few standard modifications and spit out a new MSI file (duplication of old file with changes).
I started writing this with a few public methods and a basic input path for the original MSI. The thing is, for this to work properly, a strict path of calls has to be followed from the caller:
var custom = CustomPackage(sourcemsipath);
custom.Duplicate(targetmsipath);
custom.Upgrade();
custom.Save();
custom.WriteSmsXmlFile(targetxmlpath);
Would it be better to put all the conversion logic as part of the constructor instead of making them available as public methods? (in order to avoid having the caller have to know what the "proper order" is):
var custom = CustomPackage(sourcemsipath, targetmsipath); // saves converted msi
custom.WriteSmsXmlFile(targetxmlpath); // saves optional xml for sms
The constructor would then directly duplicate the MSI file, upgrade it and save it to the target location. The "WriteSmsXmlFile is still a public method since it is not always required.
Personally I don't like to have the constructor actually "do stuff" - I prefer to be able to call public methods, but it seems wrong to assume that the caller should know the proper order of calls?
An alternative would be to duplicate the file first, and then pass the duplicated file to the constructor - but it seems better to have the class do this on its own.
Maybe I got it all backwards and need two classes instead: SourcePackage, TargetPackage and pass the SourcePackage into the constructor of the TargetPackage?
I'd go with your first thought: put all of the conversion logic into one place. No reason to expose that sequence to users.
Incidentally, I agree with you about not putting actions into a constructor. I'd probably not do this in the constructor, and instead do it in a separate converter method, but that's personal taste.
It may be just me, but the thought of a constructor doing all these things makes me shiver. But why not provide a static method, which does all this:
public class CustomPackage
{
private CustomPackage(String sourcePath)
{
...
}
public static CustomPackage Create(String sourcePath, String targetPath)
{
var custom = CustomPackage(sourcePath);
custom.Duplicate(targetPath);
custom.Upgrade();
custom.Save();
return custom;
}
}
The actual advantage of this method is, that you won't have to give out an instance of CustomPackage unless the conversion process actually succeeded (safe of the optional parts).
Edit In C#, this factory method can even be used (by using delegates) as a "true" factory according to the Factory Pattern:
public interface ICustomizedPackage
{
...
}
public class CustomPackage: ICustomizedPackage
{
...
}
public class Consumer
{
public delegate ICustomizedPackage Factory(String,String);
private Factory factory;
public Consumer(Factory factory)
{
this.factory = factory;
}
private ICustomizedPackage CreatePackage()
{
return factory.Invoke(..., ...);
}
...
}
and later:
new Consumer(CustomPackage.Create);
You're right to think that the constructor shouldn't do any more work than to simply initialize the object.
Sounds to me like what you need is a Convert(targetmsipath) function that wraps the calls to Duplicate, Upgrade and Save, thereby removing the need for the caller to know the correct order of operations, while at the same time keeping the logic out of the constructor.
You can also overload it to include a targetxmlpath parameter that, when supplied, also calls the WriteSmsXmlFile function. That way all the related operations are called from the same function on the caller's side and the order of operations is always correct.
In such situations I typicaly use the following design:
var task = new Task(src, dst); // required params goes to constructor
task.Progress = ProgressHandler; // optional params setup
task.Run();
I think there are service-oriented ways and object-oritented ways.
The service-oriented way would be to create series of filters that passes along an immutable data transfer object (entity).
var service1 = new Msi1Service();
var msi1 = service1.ReadFromFile(sourceMsiPath);
var service2 = new MsiCustomService();
var msi2 = service2.Convert(msi1);
service2.WriteToFile(msi2, targetMsiPath);
service2.WriteSmsXmlFile(msi2, targetXmlPath);
The object-oriented ways can use decorator pattern.
var decoratedMsi = new CustomMsiDecorator(new MsiFile(sourceMsiPath));
decoratedMsi.WriteToFile(targetMsiPath);
decoratedMsi.WriteSmsXmlFile(targetXmlPath);

Entity Framework: Cancel a property change if no change in value

When setting a property on an entity object, it is saving the value to the database even if the value is exactly the same as it was before. Is there anyway to prevent this?
Example:
If I load a Movie object and the Title is "A", if I set the Title to "A" again and SaveChanges() I was hoping that I wouldn't see the UPDATE statement in SqlProfiler but I am. Is there anyway to stop this?
Yes, you can change this. Doing so isn't trivial, however, in the current version of the Entity Framework. It will become easier in the future.
The reason you're seeing this behavior is because of the default code generation for the entity model. Here is a representative example:
public global::System.Guid Id
{
get
{
return this._Id;
}
set
{
// always!
this.OnIdChanging(value);
this.ReportPropertyChanging("Id");
this._Id = global::System.Data.Objects.DataClasses
.StructuralObject.SetValidValue(value);
this.ReportPropertyChanged("Id");
this.OnIdChanged();
}
}
private global::System.Guid _Id;
partial void OnIdChanging(global::System.Guid value);
partial void OnIdChanged();
This default code generation is reasonable, because the Entity Framework doesn't know the semantics of how you intend to use the values. The types in the property may or may not be comparable, and even if they are, the framework can't know how you intend to use reference equality versus value equality in all cases. For certain value types like decimal, it's pretty clear, but in a general sense it's not obvious.
You, on the other hand, know your code, and can customize this some. The trouble is that this is generated code, so you can't just go in and edit it. You need to either take over the code generation, or make it unnecessary. So let's look at the three options.
Take over the code generation
The essential approach here is to create a T4 template which does the code behind, and that the default code generation from the Entity Framework. Here is one example. One advantage of this approach is that the Entity Framework will be moving to T4 generation in the next version, so your template will probably work well in future versions.
Eliminate code generation
The second approach would be to eliminate cogeneration altogether, and do your change tracking support manually, via IPOCO. Instead of changing how the code is generated, with this approach you don't do any code generation at all, and instead provide change tracking support to the Entity Framework by implementing several interfaces. See the linked post for more detail.
Wait
Another option is to live with the Entity Framework the way it is for the time being, and wait until the next release to get the behavior you desire. The next version of the Entity Framework will use T4 by default, so customizing the code generation will be very easy.
According to MSDN:
The state of an object is changed from
Unchanged to Modified whenever a
property setter is called. This occurs
even when the value being set is the
same as the current value. After the
AcceptAllChanges method is called, the
state is returned to Unchanged. By
default, AcceptAllChanges is called
during the SaveChanges operation.
Looks like you'll want to check the value of properties on your Entity objects before you update to prevent the UPDATE statement.
At a generic level, if your entities are implementing INotifyPropertyChanged, you don't want the PropertyChanged event firing if the value is the same. So each property looks like this :-
public decimal Value
{
get
{
return _value;
}
set
{
if (_value != value)
{
_value = value;
if (_propertyChanged != null) _propertyChanged(this, new PropertyChangedEventArgs("Value"));
}
}
}
Hope that's relevant to Entity Framework.
One thing you can do is just wrap the property yourself using a partial class file, and then use your property instead of the first one:
public sealed partial class MyEFType {
public string MyWrappedProperty {
get {
return MyProperty;
}
set {
if (value == MyProperty)
return;
MyProperty = value;
}
}
}
It wouldn't be very practical to do this to every property, but if you have a need to detect that a particular property has actually changed and not just been written to, something like this could work.