3
votes

In my instance of Orchard, I have a custom content type which has a custom content part. In the "editor driver" for the content part, I need to check to see if the container content item is valid (i.e. passes validation).

The normal ModelState won't work here because of how Orchard works - and I can determine if the content part is valid, but I need to know about the entire content item (there are other content parts within the content item).

I know there are ways to execute code once a content part is published / created using lifecycle events (http://docs.orchardproject.net/Documentation/Understanding-content-handlers), but there's no way (that I know of) to pass those events information.

Basically, I need to execute a method if the content item is valid, and I need to pass the method information contained within the ViewModel.

There may be (and probably is) a better way to do this, but I'm struggling to find a way within Orchards framework.

sample code:

//POST
protected override DriverResult Editor(EventPart part, IUpdateModel updater, dynamic shapeHelper)
{
    var viewModal = new EventEditViewModel();

    if (updater.TryUpdateModel(viewModal, Prefix, null, null))
    {
        part.Setting = viewModal.Setting;
    }

    //here's where I need to check if the CONTENT ITEM is valid or not, for example
    if (*valid*)
    {
        DoSomething(viewModal.OtherSetting);
    }

    return Editor(part, shapeHelper);
}

Note: I am using Orchard version 1.6.

1
Can you give more details about the scenario? Why do you need to do that?Bertrand Le Roy

1 Answers

4
votes

No easy way to do that from inside a driver, I'm afraid. Too early. You can access other parts by doing part.As<OtherPart>, but those may or may not be updated yet at this point.

You may try utilizing handlers and OnPublishing/OnPublished (and other) events like this:

        OnPublishing<MyPart>((ctx, part) =>
        {
            // Do some validation checks on other parts
            if (part.As<SomeOtherPart>().SomeSetting == true)
            {
                notifier.Error(T("SomeSetting cannot be true."));
                transactions.Cancel();
            }
        });

where transactions is ITransactionManager instance, injected in ctor.

If you need more control, writing your own controller for handling item updates/creates is the best way to go.

In order to do that (assuming you already have your controller in place), you need to use handler OnGetContentItemMetadata method to point Orchard to use your controller instead of the default one, like this:

        OnGetContentItemMetadata<MyPart>((context, part) =>
        {
            // Edit item action
            context.Metadata.EditorRouteValues = new RouteValueDictionary {
            {"Area", "My.Module"},
            {"Controller", "Item"},
            {"Action", "Edit"},
            {"id", context.ContentItem.Id}};

            // Create new item action
            context.Metadata.CreateRouteValues = new RouteValueDictionary {
            {"Area", "My.Module"},
            {"Controller", "Item"},
            {"Action", "Create"});
        });