1

With FubuMVC, I'm not sure what the best way is to determine the current action's output model type. I see different objects that I could get the current request's URL from. But that doesn't lead to a very good solution.

What's the easiest way to get the current action's output model type from the behavior?

If this isn't a good practice, what's a better way?

Mark Rogers
  • 96,497
  • 18
  • 85
  • 138
  • This isn't a good practice because you'd be doing it the hard way and not taking advantage of Fubu's ability to wire up conventions. Before I answer this question, I'd like to know more about what you're trying to do and why. This will help me give you a better answer. Could you please elaborate and give some background? – chadmyers Mar 01 '11 at 19:34
  • @Chadmyers - thanks for the interest. In your excellent response to [How do you create a FubuMVC behavior that copies site configuration values to an output model?](http://stackoverflow.com/q/5123186/25847), the crucial code line `var viewModel = _request.Find().First()` caused a small issue for me. The problem is that I've created an inheritance hierarchy around a base class ViewModel (probably not a good idea). The behavior appears to only set the site configuration values if I've chosen the correct ViewModel subclass. – Mark Rogers Mar 01 '11 at 19:46
  • Most of my non-ajax page views return ViewModel or a descendent of it. Instead of wiring a behavior for each subclass of ViewModel, I would prefer one behavior. I partly solved this problem, by first refactoring out some unnecessary inheritance and by creating a templated behavior. – Mark Rogers Mar 01 '11 at 19:49
  • @Mark - OK, I think I get it. The example I wrote in the previous article was a simplistic to show you the basics of post-action behavior wiring-up. I'm working up a sample now and I should have it to you tomorrow. – chadmyers Mar 01 '11 at 23:41
  • @Chadmyers - wow, thanks so much, I can't wait to read it. – Mark Rogers Mar 01 '11 at 23:42
  • 1
    One other thought I had: If you just want some settings in your view, it's probably best just to use <%: Get().SomeSettingProperty %> in your view. This avoids unnecessary noise properties on your output models. – chadmyers Mar 01 '11 at 23:42

1 Answers1

2

First, I'm assuming you've already got your settings object(s) set up in StructureMap and have the ISettingsProvider stuff already wired up.

The best, simplest thing to do would be just to pull the settings in the view, like this:

<%: Get<YourSettingsObject>().SomeSettingProperty %>

If you insist on having these be a property on your output model, then continue reading:

Let's say you had a settings object like this:

    public class OutputModelSettings
    {
        public string FavoriteAnimalName { get; set; }
        public string BestSimpsonsCharacter { get; set; }
    }

Then you had an output model like this:

    public class OutputModelWithSettings
    {
        public string SomeOtherProperty { get; set; }
        public OutputModelSettings Settings { get; set; }
    }

You'll need to do a few things:

  1. Wire up StructureMap so that it will do setter injection for Settings objects (so it will automatically inject the OutputModelSettings into your output model's "Settings" property.

    Set up a setter injection policy in your StructureMap initialization code (a Registry, Global ASAX, your Bootstrapper, etc -- wherever you set up your container).

    x.SetAllProperties(s => s.Matching(p => p.Name.EndsWith("Settings")));
    
  2. Create your behavior to call StructureMap's "BuildUp()" on the output model to trigger the setter injection. The behavior will be an open type (i.e. on the end) so that it can support any kind of output model

    public class OutputModelSettingBehavior<TOutputModel> : BasicBehavior
        where TOutputModel : class
    {
        private readonly IFubuRequest _request;
        private readonly IContainer _container;
    
        public OutputModelSettingBehavior(IFubuRequest request, IContainer container)
            : base(PartialBehavior.Executes)
        {
            _request = request;
            _container = container;
        }
    
        protected override DoNext performInvoke()
        {
            BindSettingsProperties();
    
            return DoNext.Continue;
        }
    
        public void BindSettingsProperties()
        {
            var viewModel = _request.Find<TOutputModel>().First();
            _container.BuildUp(viewModel);
        }
    }
    
  3. Create a convention to wire up the behavior

    public class OutputModelSettingBehaviorConfiguration : IConfigurationAction
    {
        public void Configure(BehaviorGraph graph)
        {
            graph.Actions()
                .Where(x => x.HasOutput &&
                            x.OutputType().GetProperties()
                                .Any(p => p.Name.EndsWith("Settings")))
                .Each(x => x.AddAfter(new Wrapper(
                    typeof (OutputModelSettingBehavior<>)
                    .MakeGenericType(x.OutputType()))));
        }
    }
    
  4. Wire the convention into your FubuRegistry after the Routes section:

    ApplyConvention<OutputModelSettingBehaviorConfiguration>();
    
  5. In your view, use the new settings object:

    <%: Model.Settings.BestSimpsonsCharacter %>
    

NOTE: I have committed this as a working sample in the FubuMVC.HelloWorld project in the Fubu source. See this commit: https://github.com/DarthFubuMVC/fubumvc/commit/2e7ea30391eac0053300ec0f6f63136503b16cca

Community
  • 1
  • 1
chadmyers
  • 3,800
  • 21
  • 29
  • Sorry about the code sample under bullet 3. SO must have a bug or something because I cannot get it formatted as code no matter what I do. – chadmyers Mar 02 '11 at 20:50
  • no problem, I tried to fix it too and no luck. I think it's maybe because it's in the middle of a numbered list, but that's just a guess. Used the first solution you mention here, it worked great. – Mark Rogers Mar 02 '11 at 21:46