How or where to get information to understand written code in Orchard modules

Topics: Administration, Core, General
Jan 16, 2012 at 9:54 AM

Hello!

How or where to get information to understand written code in Orchard modules?

For example: how to dynamically bind the controller and  view?I want to understand all the code Orchard.Thanks!

Jan 16, 2012 at 11:17 AM

The documentation site is a good place to start. Once you've familiarised yourself with the concepts there you can ask more specific questions.

What do you mean by "dynamically bind the controller and view", can you elaborate? Orchard is MVC underneath everything, so controller/view concepts are mostly exactly the same as in MVC.

Jan 17, 2012 at 9:00 AM

For example: ...OrchardLocal/Admin/Contents/Create/Page this page to create a new page.And I want to understand how this page generating.Controller of this page is  ...Orchard.Web\Core\Contents\Controllers\AdminController.cs and action "Create".This action(Create) and view(unknown, I cannot to recognize) how interact?Where I can to get information about this in documentation?

Thanks!

Coordinator
Jan 17, 2012 at 9:08 AM

Seems like you need to learn about basic ASP.NET MVC concepts in general. There are plenty of books, documentation and videos on that out there.

Jan 17, 2012 at 10:12 AM

Can I to get information about Display method in view?

For example: Display(Model) .How this method generating view?Where I can view the code of this method?

Jan 17, 2012 at 10:56 AM

That's a fairly core Orchard feature, and generally you just have to start digging through the code to find out how things like this work; there's little or no documentation (although, since I've been digging into a lot of these areas myself, I've started trying to write some tutorials on some of the harder-to-understand concepts).

Display is a dynamic object. It's stored on WebViewPage<TModel>. You can easily find this out by right-clicking on it and "Go To Definition" (same as any C# method or property). Note: you need Orchard's full source repository from codeplex if you want to follow this, which I strongly advise if you want to dig this deep!

Then you'll see it's actually returning the private object _display. So we can right-click on that and "Find All References" to see when it gets set.

So that happens in InitHelpers():

            _display = DisplayHelperFactory.CreateHelper(ViewContext, this);

DisplayHelperFactory looks like this:

 

        private IDisplayHelperFactory _displayHelperFactory;
        public IDisplayHelperFactory DisplayHelperFactory {
            get {
                return _displayHelperFactory ?? (_displayHelperFactory = _workContext.Resolve<IDisplayHelperFactory>());
            }
        }

So that's a dependency being resolved by Autofac. Now we can Find All References for IDisplayHelperFactory, and this leads us to Orchard.DisplayManagement.Implementation.DisplayHelperFactory.

Finally we've followed the trails of breadcrumbs to the actual code where the Display helper is instanced:

        public dynamic CreateHelper(ViewContext viewContext, IViewDataContainer viewDataContainer) {
            return ClayActivator.CreateInstance<DisplayHelper>(
                _behaviors,
                _displayManager,
                _shapeFactory,
                viewContext,
                viewDataContainer);
        }

        class DisplayHelperBehavior : ClayBehavior {
            public override object InvokeMember(Func<object> proceed, object target, string name, INamedEnumerable<object> args) {
                return ((DisplayHelper)target).Invoke(name, args);
            }           
        }

As you can see it's an actually very simple Clay object. A couple of days ago I wrote Part 1 of a nice Clay tutorial which I'll tidy up and post later if you want more :)

Jan 17, 2012 at 11:03 AM

Oh, I'll just post the code for DisplayHelper because it contains the actual functionality. It looks like they started writing it pre-Clay so it doesn't properly use Behaviors:

    /// <summary>
    /// Refactor: I this doesn't really need to exist, does it? 
    /// It can all be an aspect of a display helper behavior implementation...
    /// Or should this remain a CLR type for clarity?
    /// </summary>
    public class DisplayHelper {
        private readonly IDisplayManager _displayManager;
        private readonly IShapeFactory _shapeFactory;

        public DisplayHelper(
            IDisplayManager displayManager,
            IShapeFactory shapeFactory,
            ViewContext viewContext,
            IViewDataContainer viewDataContainer) {
            _displayManager = displayManager;
            _shapeFactory = shapeFactory;
            ViewContext = viewContext;
            ViewDataContainer = viewDataContainer;
        }

        public ViewContext ViewContext { get; set; }
        public IViewDataContainer ViewDataContainer { get; set; }

        public object Invoke(string name, INamedEnumerable<object> parameters) {
            if (!string.IsNullOrEmpty(name)) {
                return ShapeTypeExecute(name, parameters);
            }

            if (parameters.Positional.Count() == 1) {
                return ShapeExecute(parameters.Positional.Single());
            }

            if (parameters.Positional.Any()) {
                return new Combined(ShapeExecute(parameters.Positional));
            }

            // zero args - no display to execute
            return null;
        }

        public class Combined : IHtmlString {
            private readonly IEnumerable<object> _fragments;

            public Combined(IEnumerable<object> fragments) {
                _fragments = fragments;
            }

            public string ToHtmlString() {
                return _fragments.Aggregate("", (a, b) => a + b);
            }
            public override string ToString() {
                return ToHtmlString();
            }
        }

        private object ShapeTypeExecute(string name, INamedEnumerable<object> parameters) {
            var shape = _shapeFactory.Create(name, parameters);
            return ShapeExecute(shape);
        }

        public object ShapeExecute(object shape) {
            var context = new DisplayContext { Display = this, Value = shape, ViewContext = ViewContext, ViewDataContainer = ViewDataContainer };
            return _displayManager.Execute(context);
        }

        public IEnumerable<object> ShapeExecute(IEnumerable<object> shapes) {
            return shapes.Select(ShapeExecute).ToArray();
        }
    }

Jan 18, 2012 at 5:14 AM

Yes, I want a Clay tutorial.Thanks!

Jan 18, 2012 at 9:09 PM

The Clay tutorial Part 1 is online: http://downplay.co.uk/tutorials/clay/down-the-rabbit-hole

I have to apologise for my theme; I designed it in a rush some time ago and haven't properly sorted it out, it's too narrow a column for the code samples, and there are other problems.

Also be warned: the information contained therein is not for the faint hearted! ;)