Skip to content

Leveraging your CSPROJ meta information

Motivation

Out of the box, a Manifest.cs file is generated, which includes the ModuleAttribute, FeatureAttribute, ThemeAttribute, and so forth, that describe the Orchard Core meta information about your projects. However, let's say you want to connect available meta properties at the CSPROJ level, i.e. such properties as $(MSBuildProjectName), $(AssemblyVersion), $(PackageTags), to name a few.

At its core, we wanted to follow a pattern similar to InternalsVisibleTo, i.e.

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
      <_Parameter1>Test.$(MSBuildProjectName)</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

The principles are the same, but in prior versions, the attribute constructors were not available for us to lean into. We also decided to provide helpful MSBuild Items as a more accessible, self-documenting shorthand input. So, while it is possible to engage directly with the constructors, i.e. InternalsVisibleTo, we will leave that as an exercise for the reader. Rather, we will focus on the Item Lists.

We also had a requirement that our assembly versions, in particular, are bumped during the build targets, so we wanted that to happen before being relayed into the Orchard Core targets. Consult with the Microsoft MSBuild documentation for broader details concerning the build properties that are available.

MSBuild Item Lists

There are several items you may be interested in, depending on your projects, i.e. whether Module, Theme, and/or any Features. There are also a couple of properties that we use during the Orchard Core targets. Obviously, one would not specify all of these in the same project, but for documentation brevity, are enumerated here. There are some caveats to mention, but overall, these are the attributes of interest.

<OrchardCoreFeatures Include="..."
                     Name="..."
                     Category="..."
                     Priority="..."
                     Description="..."
                     Dependencies="..."
                     DefaultTenant="..."
                     AlwaysEnabled="..." />
<OrchardCoreModules Include="..."
                    Name="..."
                    ModuleType="..."
                    Category="..."
                    Priority="..."
                    Description="..."
                    Author="..."
                    Version="..."
                    Website="..."
                    Dependencies="..."
                    Tags="..."
                    DefaultTenant="..."
                    AlwaysEnabled="..." />
<OrchardCoreThemes Include="..."
                   Name="..."
                   Base="..."
                   Category="..."
                   Priority="..."
                   Description="..."
                   Author="..."
                   Version="..."
                   Website="..."
                   Dependencies="..."
                   Tags="..."
                   DefaultTenant="..."
                   AlwaysEnabled="..." />

With all properties described as follows.

Property Type Description
Include string 1 Required, signals MSBuild that an item list is supported, which Identity serves as the attribute Id.
Name string Optional, human readable name for the module or feature.
Base string Optional, the base theme from which the assembly is derived. Not applicable to either features or modules.
ModuleType string Optional author provided Type; defaults to "Module" or "Theme". Not applicable to features since this is a Module base class property. 2
Category string Optional category for the feature.
Priority int 1 Optional integer priority, given as a string, defaults to 0; lower priority given precedence.
Description string Optional descriptive text.
Author string Optional, author provided identification.
Version string Optional, recommended, semantic versioning text, defaults to "0.0".
Dependencies list Optional, semi-colon delimited list of Module Identifier dependencies. 3
Tags list Optional, semi-colon delimited list of tags. 3
DefaultTenant bool 1 Optional, Boolean, true|false, defaults to false.
AlwaysEnabled bool 1 Optional, Boolean, true|false, defaults to false.

[1] MSBuild relays all meta data as string, leaving authors to contend with either string or object type conversions i.e. either int or bool, which is fine for our purposes.
[2] Depending on the Attribute context, ModuleAttribute yields "Module", ThemeAttribute yields "Theme" by default.
[3] Defaults to semi-colon delimited, since that is also the CSPROJ delimiter. Also supports space or comma delimiting.

And for convenience, you may specify all of your assembly Orchard Core attributes using one, top level item list.

<OrchardCoreAttributes Include="..."
                       Type="..."
                       ... />
Property Type Description
Type string Commonly either, "feature", "theme" or "module". Anything else not "feature" or "theme" assumes Module.

Otherwise, the OrchardCoreAttributes should include all the same properties that the desired Type would require.

Targets order dependencies

A couple of convenience MSBuild properties are provided, which authors may leverage in order to accommodate their internal target build orders.

Property Default Description
OrchardCoreEmbeddingAfterTargets AfterResolveReferences Orchard Core assembly embedding to occur after these targets.
OrchardCoreEmbeddingBeforeTargets GenerateAssemblyInfo Orchard Core assembly embedding to occur before these targets.

We do not recommend changing the defaults in any way, but rather to append with your custom targets as desired, i.e.

<PropertyGroup>
  <OrchardCoreEmbeddingAfterTargets>$(OrchardCoreEmbeddingAfterTargets);MyCustomTarget<OrchardCoreEmbeddingAfterTargets>
  <!--                                                                 ^^^^^^^^^^^^^^^ -->
</PropertyGroup>

Some caveats

Per assembly, the following heuristics are detected by the Orchard Core build targets:

  • Only one Module may be defined
  • Only one Theme, which is also a Module may be defined
  • A Module and a Theme may not both be defined
  • Any number of purely Feature (i.e. non-Module nor Theme) attributes may be defined

Drop the Manifest CSharp file

When you are happy with your CSPROJ item lists, then you may comment out the contents of the Manifest.cs file, or delete it altogether from your project, at your discretion.

Summary

In this article we described how to leverage Orcard Core CSPROJ item lists and properties in order to enrich and get the absolute most from your authoring experience.

Happy coding!


Last update: April 14, 2022