Domanda

crosspost: https://orchard.codeplex.com/discussions/459007

First question I have is what would be the repercussions of having 2 PartHandlers for the same Part in 2 different modules?

I got into this predicament because I have to run a method once a specific Content Type is created. It would be as easy to hook onto OnCreated for the part, however, here is my scenario:

  • Module A contains the part and the original handler
  • Module B contains the service where the method is
  • Module B has a reference to Module A

Therefore, I am unable to reference Module B within Module A (circular reference). So what I did was to copy the exact same PartHandler in Module A and placed it in Module B.

Would anything be wrong with that?

Then comes my second question, which I think could solve all these problems: Can we create a PartHandler for the Content Item's default Content Part? (i.e. the part where all custom fields are attached to)

This would definately make things easier as I could consolidate stuff that need to run there.

UPDATE 1 (to better explain question 2)

    ContentDefinitionManager.AlterPartDefinition("EventItem",           
      builder => builder                         
                    .WithField("StartDate", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("Start Date")
                        .WithSetting("DateTimeFieldSettings.Display", "DateOnly")
                        .WithSetting("DateTimeFieldSettings.Required", "true"))
                    .WithField("StartTime", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("Start Time")
                        .WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
                    .WithField("EndDate", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("End Date")
                        .WithSetting("DateTimeFieldSettings.Display", "DateOnly"))
                    .WithField("EndTime", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("End Time")
                        .WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
                    .WithField("Intro", cfg => cfg
                        .OfType("TextField")
                        .WithDisplayName("Intro")
                        .WithSetting("TextFieldSettings.Flavor", "textarea"))

    ContentDefinitionManager.AlterTypeDefinition(
        "EventItem"
        , cfg =>
            cfg
                .DisplayedAs("Event Item")                        
                .WithPart("TitlePart")
                .WithPart("EventItem")
                .WithPart("LocationPart")   
                .WithPart("AutoroutePart", builder => builder
                    .WithSetting("AutorouteSettings.AllowCustomPattern", "true")
                    .WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
                    .WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: 'learn/events/{Content.Slug}', Description: 'learn/events/event-title'}]")
                    .WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
                .WithPart("CommonPart")
                .Draftable()
                .Creatable()
    );

I'm talking about creating a ContentHandler for the EventItem part which holds all the custom fields. How can I go about it when EventItemPart is not defined in any class in the solution?

The following below won't work since it can't find the class EventItemPart:

OnCreated<EventItemPart>((context, keynotes) =>
    questionService.SetDefaultQuestions(context.ContentItem));
È stato utile?

Soluzione

Cross-answer as well.

  1. Bertrand's perfectly right. Why do you need to reference B in A in first place? If the service from B needs A and A needs this service, then it belongs to A (at least the interface - contract).

    You can always split interface and actual implementation for your service, having one in different module than another. If implementation of your service requires stuff from B, then put the interface in A, but actual implementation in B. This way A doesn't even need to know about the existence of B, but still be able to use the service via it's interface - it's the beauty of IoC pattern and Orchard modularity:)

  2. You may use ContentPart or IContent as a type argument in handler generic methods. It's perfectly valid. This way you'd be able to plug in to events on all items, and perform custom filtering afterwards (based on type name, some field existence etc.). In your case it may look like:

    OnCreated<ContentPart>((context, part) => 
    {
        if(part.ContentItem.ContentType != "EventItem") return;
        questionService.SetDefaultQuestions(context.ContentItem);
    });
    

Update: no need to do this: .WithPart("EventItem"). This 'fake' part will be automatically added by framework.

Altri suggerimenti

Cross-answer:

  1. none However, repeating yourself is almost always wrong, especially if it's done for a bad reason. Why is are the service and the part in two different modules? Why does A need B? A circular reference indicates tight coupling. If the tight coupling is justified, then it should happen in a single module. If it's not, then you need to re-do your design to remove it.

  2. You can create a handler for anything, but your explanation of your scenario is way to vague and abstract to give any useful advice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top