Creating content in Driver Editor method

Topics: Writing modules
Jan 14, 2012 at 5:48 PM

I've got a part used to manage 1-N relationships between two content types in my module (there are a couple of implementation-specific reasons why I'm unable to use lists or Science Project for this). The Editor post method creates a content item based on user input, and displayed them as a list from the editor get method. This works reasonably well apart from one weird issue that I can't get my head around.

On pressing save, after the content items are created, the Editor post method ends with 

return Editor(part, shapeHelper);

and I would expect that when the page has finished loading it would display the list of content items, but they aren't displayed until you refresh the page again. The content items are created and published correctly, just not shown until the request (and transaction within which the content items have been created) has finished.

I thought this could be fixed by adding

_orchard.ContentManager.Flush();

to the end of my editor post method, but this does not produce the desired effect. I've been looking at this all day to no avail, can anyone offer a suggestion?

 

Jan 14, 2012 at 6:28 PM

There are some methods in Science Project that create items around the same time in the process and it works for me (I also use ContentManager.Flush()). Perhaps some data is cached somewhere along the line, can you show your full driver code?

Slightly curious as to what implementation details would prevent you using Science Project; I designed it to be extensible for any possible scenario, so if there's some situation I haven't accounted for I'd like to know so I can fix it in a future version! (It might just be that you don't realise you can extend it that way, or it might be something that will be supported better in the forthcoming v1 release).

Jan 14, 2012 at 9:37 PM

Thanks for the reply Pete. It's not a reflection on Science project - more on our project! We are already working with a rather large and complex model, I felt that science project would add further complexity that we just don't need. Switching over would require rather a lot of re factoring of code that we've been working on for nearly a year, and I really don't want to switch over now we have 20+ modules all working nicely with each other.

Anyway, back to the issue at hand... It's a bit of a pain but due to the nature of the project I can't post the full driver's code, but it is nothing out of the ordinary. A content item is created, then published (I've got commands that do this and they work correctly). The driver then calls Flush() and returns back to the Editor get method.

A distilled version would look like this:

protected override DriverResult Editor(BPart part, IUpdateModel updater, dynamic shapeHelper){ 
var model = new BPartEditorViewModel(); updater.TryUpdateModel(model, Prefix, null, null); item = _orchard.ContentManager.Create("BItem", VersionOptions.Draft); 
item.As<RoutePart>().Title = "";
// sets some other stuff here...
_orchard.ContentManager.Publish(item.ContentItem);
_orchard.ContentManager.Flush();
return Editor(part, shapeHelper);
}

Interesting that you mention caching - do you mean caching that we've specifically implemented or elsewhere in Orchard itself?

I'm working on the assumption that calling Flush causes all changes to content items to be written to the database, and therefore future calls to IContentManager.Query() would reflect this - is that incorrect?

Jan 15, 2012 at 12:54 PM

Ok, so now I'm a little embarrassed... We've got a handler loading the list of sub-items for the part during the OnLoading event. The part is loaded and the sub-items are set against it. Then the content item is created, and OnLoading isn't called again during the request, so the item doesn't appear until the next request. So to work around this we've added some code to actually add it to the list.

Thanks for your suggestions. I'll be back later, I've just got to go and kick myself a few times.

Jan 15, 2012 at 1:30 PM
Hehe ... That's what i meant by 'cached' really ... That the data must be preloaded *somewhere* :)

Another recommendation: mostly it's a bad idea to load any amount of data in a handler. There are serious performance implications if e.g. you display a summary list and each item is performing a full query on load, even if you don't actually display the item! Or even just processing a list if items in memory, that handler will run for each item.

The best practise is to populate a lazy loader from the content handler instead ... So the data is available on demand but only loaded if you need it. And then you wouldn't need any special handling, the query would only run *after* you created the item.





kobowi <notifications@codeplex.com> wrote:


From: kobowi

Ok, so now I'm a little embarrassed... We've got a handler loading the list of sub-items for the part during the OnLoading event. The part is loaded and the sub-items are set against it. Then the content item is created, and OnLoading isn't called again during the request, so the item doesn't appear until the next request. So to work around this we've added some code to actually add it to the list.

Thanks for your suggestions. I'll be back later, I've just got to go and kick myself a few times.

Jan 15, 2012 at 2:04 PM

Thanks for the Lazy<> suggestion, hadn't realized there would be such a performance hit... Time to review some modules methinks.

Jan 15, 2012 at 2:19 PM
It's a problem i started hitting pretty quickly with science project. I came up with a fairly convoluted method of both lazy loading the connections as well as tracking newly added ones without having to requery (since for various reasons i might have to hit the query before the driver updates, e.g. to check the connection doesn't already exist!) But yeah it's crucial to be aware of when and where queries are getting enumerated.


kobowi <notifications@codeplex.com> wrote:


From: kobowi

Thanks for the Lazy<> suggestion, hadn't realized there would be such a performance hit... Time to review some modules methinks.