Displaying Editor Templates on a custom theme.

Displaying Editor Templates on a custom theme.

 

Disclaimer: this post can be "advanced stuff" for someone who is starting with orchard. Because of this, I will try to keep it simple and build it with the minimum code necessary. 

 

Usually when you're developing a web application in Orchard and you want to edit a content item, you have two options:

 

1) Do it on the dashboard. I have to admit that the design of the dashboard is old and its complexity can scare your customer/user. Furthermore if you're developing some kind of web managament, you don't want to have two "admin" panels for your users. So this option is not valid for that *scenario*.

 

2) Write a controller for each content that you want to expose to your user. The problem with this one is that you lose most of the "design" conventions and probably you have to write tons of code.

 

But there is another option: building a controller to rule them all, just like the dashboard does. 

 

Starting with the easiest scenario, display a generic content item:

 

 [Themed]

        public ActionResult Index(int idContentItem) {

            var contentItem = contentManager.Get(idContentItem);

            dynamic model = contentManager.BuildDisplay(contentItem);

            return View((object)model);

        }

 

(As I said, this is the simplest code, don't use it in production because you're not providing security to your application, same is applied to the following snippets) So it gets the parameter, searches for the content item (it has to exist) and we ask the content manager to build the display (internally it calls the display method defined in driver for each part attached to the content item). We also have to define a View with @Display(Model) inside.

 

Something similar is done by default by Orchard, so nothing new here. It becomes more interesting when we want to edit (or create) our content item. For the Get version of the Edit, it's the same as before, we just change BuilEditor, this time it will call the Editor method in the drivers.

 

[Themed]

        public ActionResult Edit(int idContentItem) {

            var contentItem = contentManager.Get(idContentItem);

            dynamic model = contentManager.BuildEditor(contentItem);

            return View((object)model);

        }

 

And the view is the following:

 

@using (Html.BeginFormAntiForgeryPost(Url.Action("EditPost"), FormMethod.Post, new { enctype = "multipart/form-data" })) {

    @Html.ValidationSummary()

    <input name="idContentItem" value="@Model.ContentItem.Id" style="display:none;" />

    @Display(Model)

}

 

We just Display the model inside of a form targeting an Action called EditPost and we add an input with the id of the content item.

 

Finally, our EditPost looks like:

 [HttpPost]

        public ActionResult EditPost(int idContentItem) {

            var contentItem = contentManager.Get(idContentItem);

            var model = contentManager.UpdateEditor(contentItem, this);

            if (!ModelState.IsValid) {

                transactionManager.Cancel();

                return View("Edit", (object)model);

            }

            return RedirectToAction("Edit", new RouteValueDictionary { { "idContentItem", contentItem.Id } });

        }

We just retrieved our ContentItem, as before, we call UpdateEditor, but this time we're passing our controller as a parameter, well, to be more precise our IUpdateModel. In order to make our controller an IUpdateModel, we only have to implement it, which is pretty easy:

    

    public class CustomContentController : Controller, IUpdateModel {

    ...

    bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {

            return TryUpdateModel(model, prefix, includeProperties, excludeProperties);

        }

 

        void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {

            ModelState.AddModelError(key, errorMessage.ToString());

        }

    ...

    }

 

  And that's it! We can now override our EditorTemplates in our Custom themes. If you want to see more of this stuff, just take a look at the AdminController in Orchard.Core, most of the code is retrieved from there.