Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Erik 14 posts 70 karma points
    Dec 04, 2013 @ 20:33
    Erik
    14

    Getting Umbraco Content - IPublishedContent vs IContent vs Node vs Document

    I'm having difficulty understanding the variety of ways to obtain a document in Umbraco. My understandings are outlined below, and I was hoping for some confirmation.

    Way 1

    var contentService = new ContentService();
    IContent content = contentService.GetById(123);
    
    • Gets the content from the database.
    • Returns both published and unpublished content.
    • Preferred way to get editable content for CRUD operations in Umbraco 6.

    Way 2

    var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
    IPublishedContent content = umbracoHelper.TypedContent(123);
    
    • Gets the content from the cache.
    • Only returns published content.
    • Preferred way to get cached content in Umbraco 6.

    Way 3

    var content = new Document(123);
    
    • Gets the content from the database.
    • Returns both published and umpublished content.
    • Old way to get editable content for CRUD operations.

    Way 4

    var node = new Node(123);
    
    • Old way to get content from the cache.
    • Only returns published content.

    I'm ultimately trying to build functionality into a custom back-office plugin that attempts to get a published content from cache, then falls back to getting unpublished content from the database, and gets a property off that document. However, it doesn't look like IPublishedContent inherits from IContent, nor does Node inherit from Document, and the way you get properties off each type of object appears to be different.

    Is there any way to easily acomplish this? Any other ways to get a document that I'm missing?

  • Jeroen Breuer 4861 posts 12135 karma points MVP 3x admin c-trib
    Dec 05, 2013 @ 12:13
    Jeroen Breuer
    2

    Hello,

    What you're saying here is correct. There is this old wiki with some more info about Node and Document: http://our.umbraco.org/wiki/reference/api-cheatsheet/difference-between-node-and-document

    If you want to get published content you simpy use umbracoHelper.TypedContent(123) and if that fails you use contentService.GetById(123). They don't inherit from eachother because they are both created to do different things.

    Jeroen

  • Rob Epler 3 posts 25 karma points
    Apr 29, 2014 @ 17:59
    Rob Epler
    2

    It would be great if there were some kind of wrapper that would accept either an IContent or IPublishedContent and could provide a unified and single way to get at everything. 

    It's kind of frustrating that unpublished content has to have its own separate data structure the way the API is right now. I'm probably going to make a wrapper, but then I'm concerned that anybody in the future looking at my work isn't going to have any idea what's going on.

     

     

  • Jeroen Breuer 4861 posts 12135 karma points MVP 3x admin c-trib
    Apr 29, 2014 @ 18:05
    Jeroen Breuer
    0

    They are different object, because they have different purposes. 

    IPublishedContent is for displaying data on the frontend of website. It's very fast.

    IContent is for modifying content which happend in the Umbraco backend. It's slower because it doesn't work with the published cache layer.

    Jeroen 

  • Erik 14 posts 70 karma points
    Apr 29, 2014 @ 20:05
    Erik
    1

    @Jeroen: But IPublishedContent and IContent both conceptually represent a document, and much of the similarities could be abstracted out to a base class or another interface.

  • Rob Epler 3 posts 25 karma points
    Apr 30, 2014 @ 22:42
    Rob Epler
    0

    Why is there an IsDraft property on IPublishedContent? There's no way to get unpublished content in that form.

     

  • Mark 11 posts 33 karma points
    Oct 22, 2014 @ 18:22
    Mark
    0

    So to carry on this discussion, has anyone come up with a lightweight way of wrapping the IContent and IPublishedContent?

    I have strongly typed types that inherit from PublishedContentModel, i use them in the front end but I also want to use the same strongly typed type to insert into the database via the content services, only thing is Services ContentService SaveAndPublishWithStatus takes a IContent type!

    Services.ContentService.SaveAndPublishWithStatus(IContent, bool)

    Kind of sinks the notion of having your own strongly typed types that inherit from IPublishedContent for the front end?

  • Jeroen Breuer 4861 posts 12135 karma points MVP 3x admin c-trib
    Oct 22, 2014 @ 18:25
  • Mark 11 posts 33 karma points
    Oct 22, 2014 @ 18:57
    Mark
    0

    Well done Jerone, that seems to build models that inherit from IPublishedContent, problem still stands?

    https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Zbu.ModelsBuilder

    How to create models that can use IPublishedContent for the front end and Iontent for contentservices operations?

  • Mark 11 posts 33 karma points
    Oct 23, 2014 @ 10:45
    Mark
    0

    There has to be a logical solution to this otherwise I can only fear the Umbraco is in fact broken!

    Anyone have any ideas?

  • Stephen 767 posts 2268 karma points c-trib
    Oct 23, 2014 @ 11:24
    Stephen
    13

    Hi all,

    Very interesting thread - trying to bring more infos here:

    • IContent is managed by IContentService and is targetted at back-end, read-write access to content. It's what you want to use when you need to manage content.
    • IPublishedContent is managed by the "content cache" and is targetted at front-end, read-only access to content. It's what you want to user when rendering content.
    • Document and INode are (roughly) the legacy equivalents of IContent and IPublishedContent. They should not be used anymore, and will eventually be obsoleted entirely. So better ignore them.

    Why have IContent vs IPublishedContent? Mostly because IContent provides all the plumbing required to manage content (edit a property, keep track of changes...) and thus is a heavy, expensive object, whereas IPublishedContent is a much lighter object oriented at improving rendering performances. In addition, IPublishedContent supports strongly-typed models to make it easier to write views.

    One important thing to understand is that "published" content really means "front-end oriented". We probably should have picked a different name (suggestions?). It is not restricted to what's actually "published". When in preview mode (ie after hitting "preview" in the back-end) the content cache has access to non-published content, and Umbraco.TypedContent(1234) can very well return an IPublishedContent (and not null) if content 1234 exists but is not published. And that content's IsDraft property would be true (this should answer @Rob's question).

    The long-term, global idea is that it should be possible to use UmbracoContext.ContentCache.GetById(5678, true) to get an IPublishedContent for the draft version of content 5678 (because of the "true" parameter, which indicates whether we should consider unpublished content or not) even though we are not currently "previewing". Unfortunately, this will not work at the moment, due to the way previewing works. Previewing requires a "preview set" or "preview context" that is created when you hit "preview" in the back-end.

    So... IPublishedContent was designed to support things that don't exist yet ;-) I am currently working on a content cache replacement that would support getting published or non-published content. Plan is to have something running in the coming months though I have no idea when it would make it in a final release.

    Which means that, in the current situation, you have to rely on dirty workarounds. But I'd rather invest time in building a cache that works as intended.

     

    That beeing said,

    It has always been my understanding that if the content cache provided an easy access to both published and non-published content, everybody would be happy and back-end would use IContent and front-end would use IPublishedContent. For example, some ppl have asked for IPropertyValueConverter support for IContent. I must say I don't understand why you'd want that: just get the corresponding IPublishedContent and be happy. Same with wanting strongly-typed IContent.

    Can we use this thread to discuss whether the "big picture" makes sense at all? Are there some situations that I fail to understand at the moment, where a mixed use of IContent and IPublishedContent would be required?

  • Mark 11 posts 33 karma points
    Oct 23, 2014 @ 11:33
    Mark
    1

    Thanks Stephen

    First use case to address is with Strongly Typed POCO's. Currently the suggestion is to inherit from IPublishedContent.

    All well and good until you want to use your POCO with ContentService.

    Any suggestions for a work around would be welcome.

  • Stephen 767 posts 2268 karma points c-trib
    Oct 23, 2014 @ 11:48
    Stephen
    0

    @Mark: why would you want to use POCO with IContent?

  • Mark 11 posts 33 karma points
    Oct 23, 2014 @ 12:14
    Mark
    1

    Simple example.

    I have a comment form that posts a POCO (CommentType) to a Controller. That controller takes CommentType and I want to use ContentService.SaveAndPublish. SaveAndPublish excepts a IContent Type but my CommentType inherits from IPublishedContent.

    public class CommentType: : Umbraco.Core.Models.PublishedContent.PublishedContentModel  
    {
            public CommentType(Umbraco.Core.Models.IPublishedContent content) : base(content) { }
            public string Comment{ get; set; } 
    }
    

    Problem is, if you create POCO's to be used as cached content and also want to create new content with the same POCO class you come totally unstuck.

    public void Post(CommentType comment)
            {
    
               var contentService = Services.ContentService;
    
               contentService.SaveAndPublishWithStatus(comment, 0);
            }
    

    Or am i missing the point?

    How do you use a single POCO for both IPublishedContent and IContent?

    Or

    How do you use a single POCO for both front end content in your Views and in your Controllers to create new content?

  • Tim 1193 posts 2655 karma points c-trib
    Oct 23, 2014 @ 12:26
    Tim
    0

    Hi Mark,

    I think that the IsDraft property is used when previewing content from the back end, which generates previews from unpublished content (although I can't say with 100% certainty, as it's not a property I've ever used).

    I'm pretty sure that iPublished Content and Content are separate because they're not really meant to interact. Content is meant purely for back end CRUD operations, and is powered by the database and IPublishedContent is meant only for read only front end stuff, and is powered by the caches, and doesn't interact with the database, so it wouldn't make sense to convert from one to the other, as the front end isn't actually designed to do that....... In fact it's possioble that the content that you get back from iPublishedContent isn't the same as what you'd get back from a Content object, as the Content object will have any unpublished changes that aren't yet live in it. Updating the Content based on data from iPublished content runs the risk of overwriting unpublished data with older data that's published. Your back end models would be sepaate from your front end ones, as they're not really the same. For example the Content object contains references to the full Content Type, as well a s a bunch of other references and properties that aren't part of iPublishedCOntent, as they're not needed on the front end usually.

    Can you give us a better idea of exactly what you're trying to achieve? Are you just trying to have the users update Umbraco properties from the front end, or something more complex?

  • Stephen 767 posts 2268 karma points c-trib
    Oct 23, 2014 @ 12:33
    Stephen
    0

    @Mark: the point here is your Post(CommentType commentType) method which is an action method of the controller, right? You want a POCO to benefit from MVC binding and then you want to save that POCO, right again? You have created a POCO for front-end rendering, but that POCO would then implement IPublishedContent and cannot be used by IContentService.

    First, I think we're talking about two different POCOs, and probably always will be, because (a) they're not real POCOs and there's some logic in them and (b) they have very different purposes and do very different things. So I don't think (at the moment) that we're going to unify both POCOs.

    That being said, anytime I've had to do that type of things I've done something along (with CommentTypeModel being a simple class not inheriting from anything):

    public void Post(CommentTypeModel model)
    {
    var commentType = contentService.GetById(model.Id);
    commentType.Comment = model.Comment;
    commentType.Whatever = model.Whatever;
    contentService.SaveAndPublishWithSatus(commentType);
    }

    And I can see how having some sort of POCO here would help.

  • Mark 11 posts 33 karma points
    Oct 23, 2014 @ 12:35
    Mark
    0

    Thanks Tim

    Are you saying that if i would like to use my own strongly typed entities for the above example I would have to have a Commment type that inherits from IPublishedContent and also a Comment type that inherits from IContent then use the specific entity for either front end reads or backend CRUD operations?

    Basically what you are saying is that there is no point in using your own POCOs as Umbraco doesn't have a way of using/mapping or converting them to either IPublishedContent or IContent depending on what you wanted to do with them?

    This makes me sad...

  • Mark 11 posts 33 karma points
    Oct 23, 2014 @ 12:37
    Mark
    0

    Thanks Stephen

    So you are saying, Strongly Typed in Umbraco isn't really as helpful as some of the tutorials and examples out there would lead us to believe.

    I continue to be sad...

  • Stephen 767 posts 2268 karma points c-trib
    Oct 23, 2014 @ 12:43
    Stephen
    0

    @Mark:

    Basically what you are saying is that there is no point in using your own POCOs as Umbraco doesn't have a way of using/mapping or converting them to either IPublishedContent or IContent depending on what you wanted to do with them?

    To some extent and although that might be sad, I think that is true. An IPublishedContent is not a true POCO and "models" are not POCOs but just strongly-typed wrappers around IPublishedContent, so your property

    public string Comment { get; set; }

    is not the right way to do it... first there's no setter on an IPublishedContent, second it's just a strongly-typed way to access a property, so it should be:

    public string Comment { get { return this.GetPropertyValue<string>("comment"); } }

    The confusion comes from that POCO notion that maybe should be better documented. Conversely, a "POCO" that would stand on top of IContent is not a "POCO" either because IContent does a lot of things. You could write a "model" for CommentType on top of IContent and maybe even use it in a controller (no idea, would need to test) but it would not be a plain POCO.

    Making sense?

  • Stephen 767 posts 2268 karma points c-trib
    Oct 23, 2014 @ 12:46
    Stephen
    0

    @Mark: sorry to make you sad ;-)

    But yes, it seems that some tutorials or examples have been misleading. Umbraco does not know how to do read/write with simple POCOs - it only handles more or less complex objects, IContent or IPublishedContent. The "models" initiative proposes to provide strongly-typed models (and "strongly-typed model" is not equivalent to "POCO") to front-end dev.

    Would be interesting to see if a similar initiative for back-end dev would be possible.

  • Tim 1193 posts 2655 karma points c-trib
    Oct 23, 2014 @ 12:46
    Tim
    0

    Hi Mark,

    I'm not sure why you'd need a separate POCO for the submit? Normally with Umbraco, I'd have a front end POCO (that may or may not inherit from iPublished content, depending on what it's for), and then in the Action methods for the forms just map the ViewModel to the Content Service object. Unless you've got a form that's got tons of fields, it's not too bad. If you want to cut down on tedious model mapping, you could use AutoMapper or similar I guess?

    I think Stephan's covered this one pretty well with his answers too (he's part of the core team, and he's waaay more knowledgable than I am).

  • Mark 11 posts 33 karma points
    Oct 23, 2014 @ 12:48
    Mark
    0

    @Stephen:

    Yes, makes sense but semantics aside it would be great if we could have our own Strongly Types entities that inherit from a single Content Type that can be used as IContent or IPublished?

    Thanks

  • Stephen 767 posts 2268 karma points c-trib
    Oct 23, 2014 @ 12:53
    Stephen
    0

    @Mark: would be great, and something to keep in mind. But not doable at the moment without important architecture changes.

  • Mark 11 posts 33 karma points
    Oct 23, 2014 @ 12:56
    Mark
    0

    Thanks Tim and thanks Stephen

  • Zac 222 posts 574 karma points
    Oct 24, 2014 @ 01:21
    Zac
    0

    Just throwing my opinion in here.

    My main complication with IContent vs IPublishedContent (which I use 99% of the time) is usually just the little things like trying to work with packages and not being able to cast my node values into strongly typed objects, and subsequently having to write lots of trivial but tricky-to-debug code or working with dynamic objects (which makes me sad).

  • Badzi 7 posts 27 karma points
    Apr 14, 2015 @ 11:38
    Badzi
    0

    @Stephen:

    Any news regarding the possibility to use UmbracoContext.ContentCache.GetById(true, 5678). I'm currenty using Umbraco 6.2.4. I can see the method but the result does not reflect the "preview" version of the page.

    Thank you for your feedback

    On the 2014-10-23 Stephen wrote :

    "The long-term, global idea is that it should be possible to use UmbracoContext.ContentCache.GetById(5678, true) to get an IPublishedContent for the draft version of content 5678 (because of the "true" parameter, which indicates whether we should consider unpublished content or not) even though we are not currently "previewing". Unfortunately, this will not work at the moment, due to the way previewing works. Previewing requires a "preview set" or "preview context" that is created when you hit "preview" in the back-end.

    So... IPublishedContent was designed to support things that don't exist yet ;-) I am currently working on a content cache replacement that would support getting published or non-published content. Plan is to have something running in the coming months though I have no idea when it would make it in a final release."

  • Stephen 767 posts 2268 karma points c-trib
    Apr 14, 2015 @ 13:45
    Stephen
    0

    @Badzi: this is work in progress but TBH is probably v8 material as it requires heavy changes to the content cache (that are well under way) that are not going to be fully backward compatible.

  • Tam Pham 11 posts 74 karma points
    Apr 23, 2015 @ 06:42
    Tam Pham
    0

    Hi all, I am using IPublishedContent for articles, it works fine in the first time, Recently, articles raise and it becomes slowly (my database size is 3GB, table umbracodNode > 100.000 records). I am using Umbraco 7.2.2 

    I try to use IContent instead of IPublishedContent but result does not change.

    I  need a solution in this case, anyone have any ideas?  

    Thanks all.

  • Stephen 767 posts 2268 karma points c-trib
    Apr 23, 2015 @ 08:29
    Stephen
    0

    Using IContent instead of IPublishedContent is going to be much slower as the IContent objects are read/writeable and optimized for handling content changes -- not for performance. So your safest bet, performance-wise, is IPublishedContent. Now, 100 000 nodes is a big number of nodes for Umbraco. IPublishedContent in itself is pretty linear, perfs-wise, so the number of nodes should not impact the cost of using one IPublishedContent. On the other hand, navigating the content tree to locate those IPublishedContent is going to become more and more expensive as the size of the Xml cache grows.

    When you write "it becomes slow"... is it a global result, on each and every page, or could it be on some pages? How are you querying for content and building eg. menus and lists? Via some XPath, or via Children(...) traversal & filtering?

    Stephan

  • Tam Pham 11 posts 74 karma points
    Apr 23, 2015 @ 09:03
    Tam Pham
    0

    @Stephan

    Thanks for your advice,

    I created categories in articles by structure as below:

    - Article

    - Cat1 (>100) items

    - Cat2 

    - Catn.

    I use root.Descendants(ALIAS).where(condtion) to get all items from article node and loop item from presentation. I think I can use Umbraco.TypeContent(id_cat1,id_cat2,id_cat3,...idn), but it is difficulty if there has a change in cms. 

    Please help me for optimization it.

  • Stephen 767 posts 2268 karma points c-trib
    Apr 23, 2015 @ 17:19
    Stephen
    0

    using root.Descendants(...).Where(...) means that you are creating an IPublishedContent object instance for each article, so potentially 100 000 objects for each request, and then convert & evaluate properties for each of those objects. This has a cost, unfortunately. The "new" cache will help here, because those objects will be created once and for all instead of being re-created from the Xml cache all the time. That being said, what you do is more or less equivalent to sequencial search in a database, ie you traverse all content and check for conditions, all the time. It would be much more efficient to create indexes (either using Lucene, or raw indexes in memory) for your most frequent queries. Making sense?

  • Tam Pham 11 posts 74 karma points
    Apr 24, 2015 @ 03:39
    Tam Pham
    0

    @Stephen

    This mean is me would use lucence api to search data instead of IPublishedContent?

     

    Thanks for your sharing.

  • Jeroen Breuer 4861 posts 12135 karma points MVP 3x admin c-trib
    May 19, 2016 @ 06:59
    Jeroen Breuer
    0

    Hello,

    I've seen some posts here that people want to use the same API. Even though IContent and IPublishedContent have different purposes I have written an experimental extension method which can convert an IContent to an IPublishedContent .

    You can find the topic here: https://our.umbraco.org/forum/extending-umbraco-and-using-the-api/77358-convert-icontent-to-ipublishedcontent

    Jeroen

  • Michael Cleverly 8 posts 28 karma points
    Jan 27, 2017 @ 15:59
    Michael Cleverly
    0

    @Stephen

    I've read through this post and other related ones, and I need to make sure I got this right.

    As of now, I will not be able to get the saved (and unpublished) data from a document, as it is only available in the preview context, is that correct?

    I need the iPublishedContent after a soft save, to generate a GridHtml page for a PDF generator. But the TypedContent() only returns the published data. And since I can't use GetGridHtml() on an iContent model; I'm pretty screwed. Or what? Do I have any options?

    Thanks.

    EDIT:

    I decided to try out Jeroen Breuer's converter; and it works like a charm for my purpose. Thanks a lot, Jeroen.

  • John Bergman 459 posts 1065 karma points
    Aug 18, 2017 @ 16:57
    John Bergman
    0

    One thing I'd like to see is the models created by the model builder have a series of public constants with the property names. This would at least allow a central collection point for all of that.

    That would allow the IContent objects to use that for the names of the properties.

  • Ken Schnell 35 posts 145 karma points
    Jul 24, 2020 @ 21:55
    Ken Schnell
    0

    @Mark

    I know really old posts here , however I thought to add an interesting article that maps POCOS to IPublishedContent.

    https://24days.in/umbraco-cms/2013/mapping-content-to-pocos/

    Perhaps this allows the functionality. I need to have access to the content properties and then send that to server side mail program.

Please Sign in or register to post replies

Write your reply to:

Draft