Vue normale

Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.
À partir d’avant-hierFlux principal

Taking Advantage of the Content Type Inheritance Model in SharePoint

In my recent post Using Content Types in SharePoint’s Site Pages Library, I mentioned using interstitial Content Types, but didn’t explain what I meant.

Taking advantage of the Content Type hierarchy is an important part of a powerful information architecture, regardless whether you’re working with documents, list items, pages, etc. I’ve talked about this in conference sessions for years, but it doesn’t seem like I have a blog post about it.

Let’s use this slide from one of those sessions to illustrate the points.

SharePoint gives us the Document Content Type “out of the box”. Every Document Library you create in SharePoint (assuming you don’t use some fancy template) has the Document Content Type enabled for it. So many people just start dumping their files into the Documents (aka Shared Documents) library with every file becoming a Document and then wonder why no magic is happening.

In the example above, I have two interstitial Content Types. (Interstitial – or interstices – are spaces between things.) I create these interstitial Content Types, but never enable them in a Document Library; they generally only exist to create a strong hierarchy.

  • Org Base Document – When I start setting up the information architecture in a tenant, I almost always create a Content Type like this, usually putting the name of the organization in place of “Org”. You may never touch this Content Type again after you create it, but I’ve had it save my bacon multiple times when someone says something like, “let’s add X to ALL our custom Content Types”.
  • Contract – This is also a Content Type which I may not ever enable in a Document Library, but it allows me to search for Content Types which inherit from it.

These days, I’m most likely to create Org Base Document and Contract at the tenant level (in the Content Type Hub, via the Content Type Gallery in the SharePoint Admin Center). We use that enterprise level capability for Content Types which *may* be used in one or more sites. It gives us a central place to manage our information architecture – where it makes sense to do so. Since I’m going to inherit from Org Base Document for all my custom Document-derived Content Types, I create it at the tenant level.

When we set up a custom Content Type and inherit from an existing Content Type, there’s a brilliant logic under the covers. The out of the box Document Content Type at the tenant level has its ContentTypeId =0x0101. 0x0101 represents a Document in every tenant. (See: Base Content Type Hierarchy | Microsoft Learn for the full list of base Content Types in SharePoint.)

When I create the Org Base Document Content Type in the Content Type Gallery, it gets a ContentTypeId which starts with 0x0101 and then has a unique GUID-like part. Here is the full hierarchy tree for the Content Types with their ContentTypeIds in my Sympmarc tenant:

Content TypeInherits fromContentTypeId
Item[System]0x01
DocumentItem0x0101
Sympmarc Base DocumentDocument0x0101002FBDBE6A1A315F438E41F10681463A61
ContractSympmarc Base Document0x0101002FBDBE6A1A315F438E41F10681463A6101
Employment ContractContract0x0101002FBDBE6A1A315F438E41F10681463A610101
Real Estate ContractContract0x0101002FBDBE6A1A315F438E41F10681463A610102

As you can see, the inheritance model makes a lot of sense. Each inheritance appends something unique to the ContentTypeId. Once I’ve enabled the appropriate Content Types in Document Libraries (in this case), I can take advantage of the hierarchy using queries like:

IntentQuery
Show me all my custom Content Type -based documentsContentTypeId:0x0101002FBDBE6A1A315F438E41F10681463A61*
Show me all the ContractsContentTypeId:0x0101002FBDBE6A1A315F438E41F10681463A6101*
Show me all the Employment ContractsContentTypeId:0x0101002FBDBE6A1A315F438E41F10681463A610101*

Show me all the Contracts is the really powerful query here, IMO. By requesting all content with a ContentTypeId which starts with the Contract Content Type’s ContentTypeId (That’s what the asterisk does for us.), it doesn’t matter if I create a new Content Type inheriting from Contract. The query will automagically continue to do what I want because the next Content Type inheriting from Contract will have a ContentTypeId of 0x0101002FBDBE6A1A315F438E41F10681463A610103. In other words, the ContentTypeId:0x0101002FBDBE6A1A315F438E41F10681463A6101* query will just pick that new content up for me without any adjustment.

Pair this good information architecture with the PnP Modern Search Web Parts, and you can build search-driven experiences which are highly specific, easily maintained, and extremely reliable. This is NOT “just Google”. It’s you building solutions to match the user stories and content needs in YOUR organization.

If you extrapolate from these examples, you probably can imagine some potential hierarchies in your information architecture which may help you create more powerful solutions for your end users. I’m curious about your thoughts, so please comment if you have examples.

Using Content Types in SharePoint’s Site Pages Library

In a modern SharePoint site, we only get one Site Pages library. We can’t create additional libraries which contain aspx pages which act like that special Site Pages library. If we could, we could meet a whole lot of interesting use cases, but it’s not an option.

One thing we *can* do is add additional Content Types to the Site Pages library. In many cases, I’ve seen people add a new column or two to the Site Pages library, but I don’t often see them adding additional Content Types. By using Content Types, you can take advantage of a richer information architecture which can span multiple sites, if needed.

Content Types are one of the primary building blocks for SharePoint, and I can’t gush about them enough. I do entire conference sessions just about Content Types! If you’re not using Content Types, you’re not holding SharePoint right, if you ask me.

I won’t go into how to create Content Types in general, but in this case, you’ll want to follow steps similar to this:

  • If the Content Type will be used only in the specific site (maybe a Benefits Overview in the HR site), then create the Content Type in the site. If there’s even a remote chance you’ll use the Content Type across sites (maybe Team Member Intro), then build it in the Content Type Hub in the SharePoint Admin Center.
  • To add a Content Type to the Site Pages library, you’ll most likely want to inherit from the out of the box Content Type called Site Page. This is the Content Type which is available in the Site Pages library by default.

In the example below, we’ve got three custom Content Types enabled on the Site Pages library: Productivity Tip, How To Guide, and Troubleshooting Guide. We’ve defined those Content Types at the tenant level: in the Content Type Gallery in the SharePoint Admin Center. Each of these Content Types inherits from an interstitial Content Type called Base [ClientName] Site Page, which inherits from Site Page. The reason we have the interstitial Content Type is so that we can say “show me all of the content which inherits from this Content Type”. That way, we can add additional peers to Productivity Tip, etc. without reconfiguring our result locations. We also have several Site Columns added to each of these Content Types so we can categorize the pages to improve findability.

Here’s what the Site Pages library looks like in one of our sites:

As you can see, the three custom Content Types are available there, and we can declare any Site Page as one of these special Content Types.

From here, we can use the PnP Modern Search Web Parts (my favorites!) to build powerful and sophisticated “slicing and dicing” for the content here or across multiple Site Pages libraries. But that’s a post for another day…

Caveats

  • If you change the Content Type of a page or set a column value, you’ve tacitly edited the page. That means you need to republish the page in order to make the change(s) visible – and even more importantly, to get the search crawler to pick up the change.
  • Because you’re adding Content Types into the Site Pages library, you may need to get creative with views in the library. At the very least, I generally change the default view from By Author (which is rarely helpful, anyway) to By Content Type. But build views which represent the tasks you want to complete: Pages which haven’t been reviewed, By Hardware Type, etc.

SharePoint Content Management: Distributed vs. Centralized

In modern SharePoint, we have content management tools which have been honed over decades of SharePoint use. At the same time, our ideas about content management have evolved over that time. People are far more comfortable maintaining content on the Web than they were when SharePoint first was released. Back then, we were often transitioning from a printed content mindset, so many organizations simply tried to apply the same sort of processes and logic to Web content that they had been using with physical content for the prior decades. This often led to quite convoluted “requirements” in order to support that traditional way of thinking about content management.

These days most people are very comfortable with the Web. For many people in the workplace now, it’s the only thing they have known. Binders like this on bookshelves above desks would be an anathema to most of them.

See the source image

So, cutting to today, we can instantiate simpler content management rules, and we can also rethink content ownership.

Centralized Content Management

In a centralized content management scenario, a particular content type – and you should think about this on a content type level – is fully managed by a central group of people. Some examples might include:

  • All Policies are managed by the Human Resources department
  • Operations is the only department which can issue a Standard Operating Procedure
  • Any Standard having to do with money or timekeeping must be written by Finance

These are perfectly legitimate scenarios. However, they require a “pinch point” in that anyone in the organization who wants to issue a policy, for example, must work with Human Resources to create and publish it. It puts the policy content management egg into one basket.

In many cases, centralized content management has been the norm for many years. Some of this harks back to the print-to-Web transition and some of it harks back to the ways SharePoint and the Web worked in their earlier days.

Distributed Content Management

In a distributed content management scenario, we allow the people who understand the content best to manage it where they manage the rest of their content. Some common scenarios include:

  • All departments can publish Policies based on their operational oversight
  • Standard Operating Procedures are certainly published by Operations, but other departments can also publish them, as needed
  • While Finance controls all financial Standards, other groups can publish them as well

For this distributed publishing to work well, we need several things in place:

  • Each group (usually departments, but it can vary based on the Content Type) creates and vets the content in their own Team Site.
  • Team Site Owners can publish content from their Team Site to their Intranet site, simply using Copy to or, if a more rigid process is required, with that process implemented with appropriate tools.
  • Each site where a specific business object will be published has the proper information architecture (Site Columns, Content Types, Document Libraries) for that business object instantiated in it.
  • The metadata used in each Content Type should provide enough information – and not much more – that’s required to display the content in several different ways:
    • In a “content center” for that Content Type or family of Content Types
    • In search-driven experiences embedded in specific pages
    • Natively in the Document Library where the content is actually stored

Distributed Publishing Example

When we work with clients, we almost always use the example of Policies to illustrate distributed publishing. Policies are a common business object which is well-understood by most people in an organization. Some organizations have many policies, some have just a few. In most cases, each department has its own set of policies which it has created.

We choose a site to use as the starting point. Usually, it’s the first group which has said they need to post Policies. n almost all cases, we first create a “base document” content type – something like Base ClientName Document. All the custom Content Types we create for the organization inherit directly or indirectly from this Base ClientName Document Content Type. In that site, we create a Content Type called Policy, which either inherits from Base ClientName Document or another parent Content Type that makes sense for hierarchy.

For a Policy, the metadata may vary from organization to organization, but we usually hove some columns like:

  • Effective Date
  • Expiration Date
  • Applies To (maybe a set of geographies or departments)

Next, we create a Document Library called Policies and enable the Policy Content Type in it, removing the default Document Content Type. We create a Policy in the Policies library – singular and plural. At this point, there’s usually a little iteration on the metadata, etc. This is a good pause to take, so we can be sure we understand how best to construct Policy to serve its purposes.

Now that we have a Content Type and it is enabled in a library, we turn to PnP.PowerShell. With PowerShell, we can export the definition on the library as a Site Script unisng Get-PnPSiteScriptFromList, like so:

Get-PnPSiteScriptFromList -Url $fullPath | Out-File "./ListName.json"

where $fullPath is the full URL to the list, like “https://contoso.sharepoint.com/sites/teamsite/lists/MyList”. Note that PnP.PowerShell doesn’t care if we’re working with a list or library: under the covers, they are basically the same thing.

This gives us a JSON file which can be instantiated as a Site Script using Add-PnPSiteScript. Then we can bundle that one Site Script into a Site Template (nee Site Design) or include additional Site Scripts if we want with Add-PnPSiteDesign. I’m going to gloss over this a little bit and come back to it in a future post.

Now we have a Site Template we can apply to any site where we want to store Policies. Even if I’m going to include the Site Script in larger Site Templates, I may set up this simple Site Template to just instantiate the Policies library. I like the atomic approach to this.

When we choose to apply this Site Template to a site, we get the Policy Content Type (defined consistently, so to SharePoint it’s the same Content Type in each site) and a Policies library with it enabled.

Now each group of people with a site can create a Policy in their library – following their processes – and we can roll all the Policies up across the tenant or across sites associated with a Hub Site very easily. Most of the time this means a custom page built using the PnP Modern Search Web Parts (just about my favorite Web Parts!). We often call this something like the Policy Center.

End users can find a Policy where it’s published, perhaps by navigating into the HR site, or go to the Policy Center page we created above. We can also expose specific sets of Policies – maybe Policies which will expire in the next month – in experiences to help with central oversight.

If you’re thinking that this is a lot of work, it really isn’t. I do it all the time – with many more Content Types in each tenant in which I work – and this whole process can be as little as a few hours of effort. Compare that to the dreadful user experience you might have if you’re just dumping Policies into libraries as a Document Content Type, wherever you might choose. And believe me, it’s more work to clean all this up after you have a lot of content in SharePoint than it is up front, or at least early on.

Also note that starting at this level doesn’t mean you can’t layer more complex processes on top later. In fact, it makes it far easier when you get to that point; everything is neatly assorted so a Policy is a Policy is a Policy.


Taking this approach is also one important part of moving up the maturity model for Microsoft 365. Check out the Maturity Model for Microsoft 365 – Management of Content Competency in the Microsoft 365 Community Docs.

Cleaning Up Content Types Orphaned from the Content Type Hub

One of my clients who doesn’t have a blog came up with a good fix the other day. Since he didn’t have a place to put it, he offered it to me to post.

Have you ever deleted a Content Type from the Content Type Hub which you had previously published – without unpublishing it first? If so, you probably have that Content Type sitting in all your Site Collections (now modern sites) and you can’t delete it because it came from the Content Type Hub.

Well, there’s a fix for that. The article I list in the Resources section below gets you there for on premises versions of SharePoint, but it says for SPO you should open a ticket with Microsoft support. (Comments about Microsoft support withheld.) No support ticket required.

If it’s a wholesale problem (lots of orphaned Content Types), then the script in the article will be helpful. After all, you need to figure out which Content Types are actually orphaned first. But if you know a specific single Content Type is an issue, you can simply recreate it using the original Name and Id.

Here’s an example, using PnP.PowerShell, of course! The important bit is line 5, where you recreate the Content Type which is orphaned. Obviously, you would use your own:

  • Tenant Name
  • Name
  • Id
  • Group
$cth = "https://sympmarc.sharepoint.com/sites/contentTypeHub"

Connect-PnPOnline -Url $cth -Interactive

Add-PnPContentType -Name "IT Template Document" -ContentTypeId "0x0101001611568CC163BF408A2B9341656A02290701" -Group "MyGroup" 

Once you’ve recreated the Content Type with the same name Name and Id, you can publish it and then unpublish it to get rid of the orphans.

The modern Content Type Gallery is a bit smarter. If you delete a Content Type from there, you’ll get this message, which basically says the Content Type – if published – will be unpublished before it is deleted. No more orphans! This is a good example why you should stop using the classic UI for the Content Type Hub.

Resources

How to Unpublish Orphaned Content Types in SharePoint, Script Provided (collabware.com) – Osama Khan

Add a Location Column to a Site Content Type

Have I ever mentioned how important Content Types are in SharePoint? Almost everything you work with in SharePoint has a Content Type. If you’re just using Document and Item, you’re really not using the platforms.

In this post, I want to talk about Site Content Types and the Location column type.

Location Columns

Sometime in the last few years, we got a cool new type of column we can use in SharePoint. In Microsoft’s infinite wisdom, it’s called either a GeoLocation column or a Location column, depending on where you interact with it. It’s got a lot of magical qualities, but I can’t easily find an end user article about those qualities. Buried in the support article List and library column types and options, you’ll read this:

Add rich location data from Bing Maps or your organization directory. The location column provides additional columns to filter, sort, and search by related information including street address, city, state, country or region, postal code, coordinates, or name.

Site Content Types

Site Content Types are the best kind of Content Types in my book because we can instantiate them across modern sites with Site Templates (nee Site Designs).

Until recently, we couldn’t create a Location column as a Site Column (to add to a Site Content Type) unless we ran the Add-PnPField PnP.PowerShell cmdlet. (See: Add a Geolocation column to a list programmatically in SharePoint) Not exactly the purview of your average information architect.

Today I wondered if this had changed – and it has!

Add a Location Column to a Site Content Type

The big thing that changed recently is that Microsoft is slooowwwlyyy moving us away from the Content Type Hub and into the Content Type Gallery. When the new Content Type Gallery was initially delivered, it was really just lipstick on a pig; it was still the Content Type Hub underneath.

Now when we go into Site Settings on a modern site and click the Site content types link, we land in the Content Type Gallery. This is pretty new, and it’s possible you don’t see it in your tenant yet, though it seems to be in all the tenants where I’m working. In the Content Type Gallery , we can add Site Columns in this new UI with the Location column type.

Let’s say I want to create a Site Content Type called Property. A very normal thing I’d want to know about a Property is its address, and I’d sure like to use a magical Location column type to capture it. Here’s the sequence.

From the home page of your modern site:

Click on the gear

Choose Site information, then View all site settings

On the ugly old Site Settings page, we still see the same old two options in the Web Designer Galleries section:

The difference is now when we click on the Site content types link, we land in the Content Type Gallery.

Once we’re here, we can build the Content Type pretty much like we would in the old UI. It’s basically the same.

The big difference for this post is we can now choose a Location column when we create a new Site Column.

See that Location in the Type column below?

When we go back to the site, we have the Location column, and it’s set up as a Site Column, so we can reuse it, maybe promote it to a Managed Property for search (though I haven’t done this), etc. Even better, we can package up that Property Content Type into a Site Template so we can instantiate it in new sites where we want the same information architecture. This latter step will require some PowerShell, and maybe you shouldn’t run with those scissors. Find a SharePoint Admin to help here.

I did run into one issue. I had already enabled the Property Content Type in a list, and the new Location column wasn’t showing up. Unfortunately, the Update sites and lists option, which we’re used to having checked by default is now NOT checked by default. So you need to be sure to click it EVERY TIME YOU MAKE A CHANGE TO THE CONTENT TYPE if you want that change to cascade down into your list or libraries. I have never unchecked that box in the past, and I consider it a “bug” that the default is unchecked now. At least it’s something we can work around. I hope Microsoft changes this back to the old behavior.

Crawled Properties Not Created From Site Columns in Modern Team Sites

You know that feeling where you’ve done something so many times and it’s worked and then one day it just doesn’t? Yeah, I just had one of those.

I’m still a big fan of the PnP Modern Search Web Parts, just like I was last week or last year. To really make them sing in your solutions, you’ll end up creating Site Columns and using Content Types. I love those things, too, but this post isn’t about why.

Over the last few weeks, when I have created Site Columns, made sure they are included in Content Types, and added content using those Content Types, the Site Columns have not shown up as Crawled Properties in the SharePoint Admin Center (More features / Search [Open] / Manage Search Schema). They simply never show up. I’ve given it overnight, then a week, then two weeks.

The sequence here is important, so to reiterate:

  • Create your Site Columns
  • Add the Site Columns to Content Types
  • Add content using those Content Types – This is the one that bites many people, including me. No content, nothing to crawl!
  • The Site Columns show up as Crawled Properties

I swear this has been a reliable way to go from Site Columns to Managed Properties (after mapping to Refinable[Type]NN Managed Properties) for years. The ultimate goal in my case is to use those Managed Properties in search-driven solutions using the PnP Modern Search Web Parts. But of course, Managed Properties have other benefits as well.

I’ve been doing this for years, and I sorta feel like I know what I’m doing. I’m not proud, so I headed over to my MVP channels, and tagged people like Agnes Molnar (@molnaragnes) and Mikael Svenson (@mikaelsvenson) in a post asking whether something had changed.

Agnes pointed out an old post from Joanne Klein (@JoanneCKlein) entitled Crawled & Managed Properties in Modern Team Sites. Turns out there’s a kooky hole in things. I have no idea why this hasn’t gotten in my way before.

If you are creating your IA (my shorthand from Site Columns and Content Types, among other things) in a modern Team Site, it’s not good enough to be an Owner. As Joanne wrote, you also need to add yourself as a Site Collection Administrator directly. (Site Permissions / Advanced permissions settings / Site Collection Administrators)

Event though you’re in the Owners group, and the Owners group is in the Site Collection Administrators, you still need to add yourself directly.

Do that, kick off a re-index of the site in question, and within moments practically, your Crawled Properties will be ready to use. None of us are quite sure why this is, but it worked in two tenants for me today, one right after the other.


In case you’re wondering, once you have the Crawled Properties in place (below, ows_SiteName, ows_ExaminerName, and ows_Jurisdiction are Crawled Properties), you can map them to Managed Properties (RefinableString00, RefinableString01, and RefinableString02 below). Those Managed Properties can then be used as filters (nee refiners) in the PnP Modern Search Web Parts or elsewhere.


Mikael also pointed me to his post Tech and me: Mapping or clearing crawled property to managed property mappings using PowerShell (or code). This looks like it might help with this problem, but more likely is most useful when the Crawled Properties are not showing due to a different bug.

Thank you Joanne, Agnes, and Mikael!

Microsoft (SharePoint) Lists and Libraries Changes for Content Types

Thanks to eagle-eyed reader Markus Bütterhoff’s (@buetti) comment on my post showing how to Group By Content Type in Modern Lists and Libraries, I learned of some recent changes for Content Types in Microsoft (SharePoint) Lists and Document Libraries. I’m not sure when these rolled out, but it must have been in the last few weeks.

As far as I can tell, all of these new capabilities work the same way in both lists and Document Libraries. I’ll say “list” below, but everything applies the same for Document Libraries.

After you’ve enabled Content Type management on the list, when you click on the Add column dropdown you’ll see Content type as an option.

This takes you to a funky little screen focused on Content Types. From what I can tell, if you’ve only enabled out of the box Content Types, it doesn’t do anything for you.

If you’ve defined any customer Content Types, then you can enable them on the list with this screen. If you’ve enabled a custom Content Type, you get some info about the Content Type and a button to remove it, but it’s not clear what else is supposed to happen here. My guess is this is the beginning of a replacement for some of the List settings classic pages.

If you click to the Show/hide columns option, you can add the Content Type to the view – painlessly. In the past, we’ve needed to navigate to the classic View settings page.

The best thing I’ve found so far, though, is what Markus pointed out to me in his comment: we can easily group by Content Type with no more query string tricks that sometimes fall down.

So easy!

It’s great to see Content Types back as first class citizens in SharePoint lists.

❌
❌