Copied to clipboard

Flag this post as spam?

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


  • mmaty 109 posts 281 karma points
    Apr 05, 2013 @ 11:21
    mmaty
    0

    IContentType: How to set the Master Content Type?

    Umbraco: 6.0.3

    ASP.NET 4.0

    Windows 7 / IIS 7.5

    Using the ContentTypeService I create a hierarchy of new content types like shown in the picture:

    Let's say, that the TeaserBase contains a property "bodyText" and the TeaserMitBild adds a Property "picture" to it's properties. All teaser types below TeaserMitBild don't have own properties, but use the inherited properties. They will be rendered in a different way.

    After creation of the property type tree all looks perfect in the Settings / Document Types view.

    EDIT: The "Generic properties" tab usually shows a message saying "Master Content Type enabled
    This Content Type uses Master as a Master Content Type. Properties from Master Content Types are not shown and can only be edited on the Master Content Type itself".

    The created DocumentTypes are missing this message.

    Also if I create a document based on the inner teaser types like "Teaser 2/3" the document doesn't show any property data editor. If the property type has own properties defined, they show up in their respective tabs. My code to create the Document Types is as follows:

    IContentType CreateDt( XElement el, IContentType parent )
    {
    //umbraco.BusinessLogic.User user = new umbraco.BusinessLogic.User( 0 );
    IContentType dt;
    if ( parent != null )
    {
    dt = new ContentType( parent.Id );
    }
    else
    {
    dt = new ContentType( -1 );
    }
    dt.CreatorId = 0;
    dt.Name = el.Attribute("Text").Value;
    dt.Description = el.Attribute("Description").Value;
    dt.Alias = el.Attribute("Alias").Value;
    dt.Icon = el.Attribute( "IconUrl" ).Value;
    dt.Thumbnail = el.Attribute( "Thumbnail" ).Value;
    this.contentTypeService.Save( dt );
    return dt;
    }

    void CreateProperty( IContentType dt, XElement propElement )
    {
    string dtname = propElement.Attribute("DataType").Value;
    var dtds = dtDefs.Where( dtDef => dtDef.Name == dtname ).ToList();
    if ( dtds.Count == 0 )
    {
    throw new Exception( "DataType " + dtname + " existiert nicht" );
    }

    Umbraco.Core.Models.PropertyType pt = new PropertyType( dtds[0] );
    pt.Name = propElement.Attribute( "Name" ).Value;
    pt.Alias = propElement.Attribute( "Alias" ).Value;
    pt.Mandatory = propElement.Attribute( "Mandatory" ).Value == "true";
    // pt.ValidationRegExp = propElement.Attribute( "ValidationRegExp" ).Value;
    // The Umbraco team forgot to provide a Property for ValidationRegExp.
    string valRegExp = propElement.Attribute( "ValidationRegExp" ).Value;
    if ( valRegExp != string.Empty )
    {
    FieldInfo fi = typeof( PropertyType ).GetField( "_validationRegExp",
    BindingFlags.NonPublic | BindingFlags.Instance );
    fi.SetValue( pt, valRegExp );
    }
    pt.Description = propElement.Attribute( "Description" ).Value;

    XAttribute tabAttr = propElement.Attribute( "PropertyTypeGroup" );
    if ( tabAttr != null )
    {
    dt.AddPropertyType( pt, tabAttr.Value );
    }
    else
    {
    dt.AddPropertyType( pt );
    }
    }

    I'm sure I'm missing something. Could anybody tell me, what the mistake is?

    Cheers
    Mirko

  • mmaty 109 posts 281 karma points
    Apr 05, 2013 @ 13:41
    mmaty
    0

    Hi all,

    I found a solution for the issue, but I think there must be a cleaner way to do it. I just add these lines in CreateDt just before returning the dt:

    if ( parent != null )
    {
      umbraco.cms.businesslogic.web.DocumentType ct = new umbraco.cms.businesslogic.web.DocumentType( dt.Id );
      ct.MasterContentType = parent.Id;
      ct.Save();
    }

    Is there any way to setting the master document type with the new API?

    Cheers
    Mirko


  • Rich Green 2246 posts 4008 karma points
    Apr 05, 2013 @ 14:01
    Rich Green
    0

    Out of interest why are you creating DocTypes via the API?

  • Morten Christensen 596 posts 2773 karma points admin hq c-trib
    Apr 11, 2014 @ 11:43
    Morten Christensen
    0

    In the new API you create the nested/inherited doc types by passing in the Parent. If when creating TeaserTab you pass it the TeaserBase ContentType.

    Pseudo code:

    var teaserTab = new ContentType(teaserBase);

    Here is a more complete example (and you can find more in the test project of Umbraco https://github.com/umbraco/Umbraco-CMS/blob/7.1.2/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs ):

    public static ContentType CreateSimpleContentType(string alias, string name, IContentType parent = null)
    {
        var contentType = parent == null ? new ContentType(-1) : new ContentType(parent);
    
        contentType.Alias = alias;
        contentType.Name = name;
        contentType.Description = "ContentType used for simple text pages";
        contentType.Icon = ".sprTreeDoc3";
        contentType.Thumbnail = "doc2.png";
        contentType.SortOrder = 1;
        contentType.CreatorId = 0;
        contentType.Trashed = false;
    
        var contentCollection = new PropertyTypeCollection();
        contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "title", Name = "Title", Description = "", HelpText = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 });
        contentCollection.Add(new PropertyType(Constants.PropertyEditors.TinyMCEAlias, DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Description = "", HelpText = "", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -87 });
        contentCollection.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) { Alias = "author", Name = "Author", Description = "Name of the author", HelpText = "", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -88 });
    
        contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
    
        //ensure that nothing is marked as dirty
        contentType.ResetDirtyProperties(false);
    
        return contentType;
    }
    

    Hope this helps,

    Morten

  • uWebshop 35 posts 140 karma points
    Apr 11, 2014 @ 11:52
    uWebshop
    0

    Morten,

    Thanks, but this will make the contenttypes nested (that was already working for us), but not setup the master content type structure.

    You can easily check, because the Generic Properties tab will tell you:

    "Master Content Type enabled
    This Content Type uses Master as a Master Content Type. Properties from Master Content Types are not shown and can only be edited on the Master Content Type itself"

    if it would work :)

     

  • mmaty 109 posts 281 karma points
    Apr 11, 2014 @ 12:00
    mmaty
    1

    Sorry for not posting the solution. It's as simple as that:

    if (parent != null)
    {
     ct = new ContentType(parent);
     ct.AddContentType(parent);
    }
    else
    {
     ct = new ContentType(-1);
    }
  • uWebshop 35 posts 140 karma points
    Apr 11, 2014 @ 12:04
    uWebshop
    0

    Mmaty,

    Thank you! Sometimes these things are very easy, but you 'just have to know'.
    It's a friday so I can overlook thing right? ;) :P

    Best,

    Arnold 

  • Morten Christensen 596 posts 2773 karma points admin hq c-trib
    Apr 11, 2014 @ 12:09
    Morten Christensen
    1

    Well there is a subtle but not very obvious difference between passing in a ContentType or an integer Id when creating a new ContentType.

    When you do var contentType = new ContentType(myParentType) then the parent ContentType will be added both as a Parent and as a Master ContentType. But if you do var contentType = new ContentType(1234) the ContentType with Id 1234 will only be added as a Parent and NOT a master.

    So having both ct = new ContentType(parent); and ct.AddContentType(parent); should be redundant as the second line in @mmaty's example is done within the constructor of ContentType. However, if you are creating a new ContentType and passing in the id of another ContnetType then yes, you would need to call AddContentType to have it added as a Master.

    Reference: https://github.com/umbraco/Umbraco-CMS/blob/7.1.2/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs#L26

    Hope this wasn't too confusing :-/

    Morten

  • mmaty 109 posts 281 karma points
    Apr 11, 2014 @ 12:11
    mmaty
    0

    The word "obvious" was made for other situations... I had to have a look into the Umbraco sources. The document type import shows the right code.

  • mmaty 109 posts 281 karma points
    Apr 11, 2014 @ 12:14
    mmaty
    0

    Oops, we had some crossposting here.

    @morten: I thought, that things work like you describe it, but it wasn't the case. I tried with U 7.0.2 and it didn't work before I added the AddContentType call.

Please Sign in or register to post replies

Write your reply to:

Draft