Orchard CMS: Exporting and importing linked content items

I am working on a software based on Orchard CMS. My module defines multiple content item types which reference each other:

content items

A DataSource defines the location of data. A DataQuery defines a query taking the referenced data as input and returning a collection of objects with properties. A DataGrid defines how the properties of the objects returned by the DataQuery are displayed in an HTML table.

Now let’s have a look at how the references between content items are handled. As an example, we’ll see how the DataQueries are referencing the DataSources.

First, the ContentPartRecord and ContentPart definition of DataQuery looks like this:

public class DataQueryPartRecord : ContentPartRecord
{
	public virtual ContentItemRecord DataSource { get; set; }
	...
}

public class DataQueryPart : ContentPart<DataQueryPartRecord>
{
	private readonly LazyField<IContent> _dataSource = new LazyField<IContent>();

	public LazyField<IContent> DataSourceField
	{
		get { return _dataSource; }
	}

	public IContent DataSource
	{
		get { return _dataSource.Value; }
		set { _dataSource.Value = value; }
	}

	...
}

Of course my parts have other fields but they are not relevant here.

The handler implements the lazy loading and record updating:

public class DataQueryHandler : ContentHandler
{
	private readonly IContentManager _contentManager;

	public DataQueryHandler(IRepository<DataQueryPartRecord> repository, IContentManager contentManager)
	{
		Filters.Add(StorageFilter.For(repository));
		_contentManager = contentManager;

		OnInitializing<DataQueryPart>(PropertySetHandlers);
		OnLoaded<DataQueryPart>(LazyLoadHandlers);
	}

	private void LazyLoadHandlers(LoadContentContext context, DataQueryPart part)
	{
		// add handlers that will load content just-in-time
		part.DataSourceField.Loader(
			() =>
				part.Record.DataSource == null
					? null
					: _contentManager.Get(part.Record.DataSource.Id, VersionOptions.AllVersions));
	}

	private static void PropertySetHandlers(InitializingContentContext context, DataQueryPart part)
	{
		// add handlers that will update records when part properties are set
		part.DataSourceField.Setter(query =>
		{
			part.Record.DataSource = query == null ? null : query.ContentItem.Record;
			return query;
		});

		// Force call to setter if we had already set a value
		if (part.DataSourceField.Value != null)
			part.DataSourceField.Value = part.DataSourceField.Value;
	}
}

The solution to export and import content items referencing each other would have been easier to describe without the lazy loading but I do have it in my code and I didn’t have the time and motivation to refactor it just for the purpose of this post. But this is not the important part so do not let the lazy loading confuse you.

On the database side, the Migrations.cs file defines the following:

// Creating table DataQueryPartRecord
SchemaBuilder.CreateTable("DataQueryPartRecord",
	table =>
		table.ContentPartRecord()
			.Column<int>("DataSource_Id");

ContentDefinitionManager.AlterPartDefinition("DataQueryPart",
	part =>
		part.Attachable()
			.WithDescription(
				"A very nice description..."));

ContentDefinitionManager.AlterTypeDefinition("DataQuery",
	cfg =>
		cfg.WithPart("CommonPart")
			.WithPart("RoutePart")
			.WithPart("DataQueryPart")
			.WithPart("LocalizationPart")
			.WithPart("IdentityPart")
			.Creatable()
			.Draftable()
			.Indexed());

Of course I actually have more columns in my table but they are not relevant here. What’s important is that the table for my ContentPartRecord contains an int column called “DataSource_Id” and referencing the ID of the DataSource record and that my content type has an IdentityPart. The IdentityPart is required anyway in order to be able to properly import the exported data and especially make sure that you update the appropriate content item if it already exists when you import the data.

Now as described in a previous post you need to implement the Importing and Exporting methods in your driver. My first implementation was exporting the referenced DataSource ID as part of the data for the DataQuery:

context.Element(part.PartDefinition.Name).SetAttributeValue("DataSource", part.DataSource.Id);

And on import, I was fetching the DataSource from the ID:

int dataSourceId = int.Parse(context.Attribute(part.PartDefinition.Name, "DataSource"));
part.DataSource = _contentManager.Get(dataSourceId, VersionOptions.AllVersions);

Now the problem is that when I create new content items they get a incrementing ID and when I delete some of them, there is gap in the IDs. Also on the other server where I will import the data, the ID of a content item on the original server might be already in use for a completely different content item. So the content item ID will always be reassigned. This means that when you import the DataSource it might get a different ID. When the DataQuery is imported, the exported ID might now point nowhere or to a completely different content item.

So what we need is some kind of ID which is maintained during export and import. Well, that’s exactly what the IdentityPart is for. This is what Orchard uses to identify whether a content item already exists and needs to be inserted or updated. The IdentityPart contains a unique Identifier which can be exported and then used during import to look up the appropriate content item:

protected override void Importing(DataQueryPart part, ImportContentContext context)
{
	...
	
	string dataSourceIdentifier = context.Attribute(part.PartDefinition.Name, "DataSourceIdentifier");
	part.DataSource = _contentManager
                .Query<IdentityPart, IdentityPartRecord>(VersionOptions.Latest)
                .Where(p => p.Identifier == dataSourceIdentifier)
                .List<ContentItem>().FirstOrDefault();
}

protected override void Exporting(DataQueryPart part, ExportContentContext context)
{
	...
	
	context.Element(part.PartDefinition.Name).SetAttributeValue("DataSourceIdentifier", part.DataSource.As<IdentityPart>().Identifier);
}

So now we got rid of the problem with changing IDs. But there is still a remaining issue. The export file contains all exported content item sorted by content type alphabetically. So the DataQueries come before the DataSources. In case the DataQuery being imported references a DataSource which does already exist, resolving the Identifier to a content item will work. But otherwise it will fail and return null.

Luckily, there is an easy workaround: when the resolved content item is null (i.e. it’s not been imported yet) we can create a dummy content item of the appropriate type, with the right Identifier and no other data. This will solve the referencing problem. And once the DataSources are processed, Orchard will update the dummy content item to contain the actual data for this content item. This only requires a small change in the Importing method:

protected override void Importing(DataQueryPart part, ImportContentContext context)
{
	...
	
	string dataSourceIdentifier = context.Attribute(part.PartDefinition.Name, "DataSourceIdentifier");
	part.DataSource = _contentManager
                .Query<IdentityPart, IdentityPartRecord>(VersionOptions.Latest)
                .Where(p => p.Identifier == dataSourceIdentifier)
                .List<ContentItem>().FirstOrDefault();
	if (part.DataSource == null)
	{
		var item = _contentManager.New("DataSource");
		var dataSourcePart = item.As<IdentityPart>();
		dataSourcePart.Identifier = dataSourceIdentifier;
		_contentManager.Create(item);
		part.DataSource = item;
	}
}

Using this we can import content items in any order and have placeholders created if the items are imported out of order and also make sure that references are kept through the export/import process.

This all may seem quite complex but once you’ve implemented it for one content type e.g. DataQuery, all you need is some copy&paste and search&replace for the other content types e.g. DataGrid.

Also, if for some reason you need to store a reference to a content item in a text form, it’s important to make sure that all referenced content items have an IdentityPart and that you reference the Identifier of this part instead of the ID of the content item. Getting the Identifier of a content item which has an IdentityPart is very easy:

var item = ... // some content item
var identityPart = item.As<IdentityPart>();
var identifier = identityPart.Identifier;

 

ASP.NET: Slow first loading time

You might have experienced the problem that when you first load a large ASP.NET application (e.g. a CMS), it takes quite some time to load. If you then reload the page or even restart the browser and load the page again, it’s quite fast. There seems to be a few possible cause for this. So this post will not give you an extensive answer as to what all could go wrong but focus on application pool recycling.

What is an Application Pool?

Application Pools are used by IIS to isolate web applications. It allows you to use different settings in different applications. This is especially important when your different applications use different security settings. Applications in different application pools run in different windows processes (w3wp.exe) and thus also provide some kind of segregation by preventing an application from interfering with other applications. So an error in one application won’t cause other applications to crash or behave unexpectedly.

What is Application Pool Recycling?

Application pool recycling basically means that when a given event occurs, the resources related to an application pool will be recovered. It is mainly useful to prevent long running application from crashing or hanging e.g. because of memory leaks. When the recycling happens, a new worker process is started which will receive new web requests and the old one is shut down (once it’s done processing current requests), so there is no downtime while recycling.

Why does recycling cause the first load to last longer ?

Many applications need to first compile scripts or DLLs on the fly. Others need to load a large amount of data and pre-process it. This is basically what’s causing the delay on the first load. Afterwards once everything is compiled and data pre-processed, everything is fast.

Whenever an application pool is recycled and the worker processes are shutdown, next time the application is called, a new worker process needs to be started and these compilation and pre-processing activities need to be performed again.

When does recycling happen?

There are basically two different ways to recycle application pools:

  1. Recycling based on configuration
  2. On-demand recycling

On-demand recycling can be done:

  • in the IIS manager
  • from the command line using appcmd
  • using Windows Management Instrumentation (WMI) i.e. the ApplicationPool.Recycle method

Automatic application pool recycling can be configured to recycle:

  • when reaching a memory threshold (virtual memory or used memory)
  • when reaching a certain number of requests
  • at a scheduled time
  • after a scheduled time

Additionally, recycling will happen, when the configuration of an application is changed or when an unhealthy ISAPI condition is reported.

How to configure when automatic application pool recycling is done?

This can be configured in the Application Pools configuration panel of the IIS manager (Go to Start -> Administrative Tools -> Internet Information Services (IIS) Manager):

Application pool configuration

Select an application pool on the left-hand side and click on Recycling on the right.

The default configuration is to recycle an application pool after 29 hours (1740 minutes):

Application Pool Recycling Settings

If there are long periods of time during which your site/application has few hits, it might be a good idea to increase this default value. Actually, except if you know that you have a memory leak somewhere and do not manage to fix it, there is no big benefit in recycling your application pools at fixed intervals. If your application is running on a server where other applications are running, you may want to used the memory based maximums. Otherwise just removing the time interval based configuration may be a good solution. If nothing else it configured, you application pool will be recycled anyway once all available memory is used.

Idle Time-out

Also note that even though strictly speaking, it’s not an automatic application pool recycling, you can configure the application pool so that worker processes are shutdown after a specified amount on time being idle i.e. not receiving new requests or processing existing requests. The default value is 20 minutes. Actually I guess in most cases it makes no sense. It’s only useful if you have so limited resources that you need to get rid of unused application pools as fast as possible. So in most cases, I’d recommend setting the idle time-out to zero:

Application pool idle time-out

How do I know when recycling has occurred?

There are two places where you can configure under which conditions an event log entry is generated when an application pool is recycled.

The first one is when you press “Next” in the dialog shown above. You will then see the following:

Recycling application pool recycling events to log

The checkbox under “Configurable recycling events” are disable in this screenshot because I haven’t configured any  trigger for an automatic application pool recycling. But if you defined e.g. a number of requests, some checkboxes will be enabled.

Another place where you can set it is the Advanced Settings dialog. Just select your application pool and press “Advanced Settings”. The following dialog will be displayed:

Application pool advanced settings

The recycling settings are the bottom and contain a section called “Generate Recycle Event Log Entry”. You can then set the appropriate entries to true to get the required event log entries.

Also remember that starting from Windows 2008, you can have an email sent when an event is triggered.

Orchard CMS: NullReferenceException when adding roles

When clicking on “Add a role” in the Users administration, I got the following exception:

System.NullReferenceException: Object reference not set to an instance of an object.
at Orchard.Roles.Services.RoleService.GetInstalledPermissions()
at Orchard.Roles.Controllers.AdminController.Create()
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass13.<InvokeActionMethodWithFilters>b__10()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass13.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass13.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)

I found a reported issue which did look similar. It was reported against Orchard CMS 1.7 and was marked as resolved. I am using Orchard CMS 1.7.2. Unfortunately, the issue details neither show in which version it was solved nor what the actual root cause was. Since it was closed by Sébastian who’s an Orchard Core developer and was actually born in the same city as I was, I could have contacted him but in-between I found out what the problem was.

Actually my problem was caused by a module I am working on. When disabling the module, it worked fine and when reactivating it, it is broken again.

The problem was in the Permissions.cs file. There were basically two problems. Basically what Orchard does when you click on “Add a role” is to get all features and their permissions. The two problem I had were:

  1. The GetPermissions() method did not returned all permissions I had defined and was returning in GetDefaultStereotypes()
  2. ReSharper had suggested me to make the setter for the Feature property private since it was not accessed anywhere.

But fixing the first one alone didn’t solve anything. I guess it was necessary to fix it but the root cause of the problem was the private setter for the Feature property. Once I made it public again it worked fine:

public Feature Feature { get; set; }

So the lesson here is that especially when working with such a system as Orchard CMS you should not blindly implement changes in the visibility of properties or methods suggested by ReSharper/Visual Studio. Since properties and methods are rarely directly referenced, your tools will very often miss some dependencies.

 

 

 

Active Directory Authentication and Authorization in Orchard CMS

Since Orchard CMS doesn’t (yet) support authentication and authorization of domain users against an Active Directory, you have to install a module to achieve this. There are handful of modules which could help. I decided to use ActiveDirectoryAuthorization by Moov2 because it was the only one which had a decent number of downloads, reviews and a project site.

If you decide to use this module, you’ll first notice that there isn’t any complete documentation how to adapt your system so that the authentication and authorization works over an Active Directory. But there is a blog article which gives some instructions. Unfortunately, the instructions seem not to be complete.

Basically when it comes to the changes to be made in your web.config, the blog post says you should “simply replace the current Forms authentication settings with the authentication settings shown below”:

    <authentication mode="Windows" />
    <roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider"/>

Unfortunately, only with this change, whenever I entered my credentials, I used to get the same dialog over and over. What’s missing here, is that you also need to add an authorization tag, thus replacing:

    <authentication mode="Forms">
      <forms loginUrl="~/Users/Account/AccessDenied" timeout="2880" />
    </authentication>

by:

    <authentication mode="Windows"/> 
    <roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider"/> 
    <authorization>
	    <allow roles="aw001\Domain Users"/>
	    <deny users="?"/>
    </authorization>

Of course, you have to replace aw001 by your domain name.

The question mark in the deny tag basically means that anonymous users will be denied access and the allow tag that all Domain Users of this particular domain will be granted access.

After that, Orchard just gave me a white page. So at least something was activated… In the logs, I found the following exception:

2014-09-25 11:36:01,653 [6] Orchard.Environment.DefaultBuildManager – Error when compiling assembly under ~/Modules/ActiveDirectoryAuthorization/ActiveDirectoryAuthorization.csproj.
System.Web.HttpCompileException (0x80004005): c:\inetpub\wwwroot\orchard\Modules\ActiveDirectoryAuthorization\Core\Authorizer.cs(144): error CS1061: ‘Orchard.ContentManagement.IContentManager’ does not contain a definition for ‘Flush’ and no extension method ‘Flush’ accepting a first argument of type ‘Orchard.ContentManagement.IContentManager’ could be found (are you missing a using directive or an assembly reference?)
at System.Web.Compilation.AssemblyBuilder.Compile()
at System.Web.Compilation.BuildProvidersCompiler.PerformBuild()
at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath)
at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResult(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetCompiledAssembly(String virtualPath)
at Orchard.Environment.DefaultBuildManager.GetCompiledAssembly(String virtualPath) in Orchard\Environment\IBuildManager.cs:line 53

I could see the line of code where this was done but still wasn’t sure what I had to do. So I googled for it. There was exactly one hit. Somehow, it looks like someone had the same problem with a completely unrelated module. This problem was solved in this module and I checked what was the code change. It turns out they only removed the call to ContentManager.Flush(). So I gave it a try, editing ActiveDirectoryAuthorization\Core\Authorizer.cs and commenting out the following line in the CreateUser method:

_contentManager.Flush();

After that I could log in.

The other problem I had was that my domain user didn’t have the permissions I thought I had assigned. The problem is that I created a role with the same name as a group of this user in Active Directory but didn’t add the domain name to it i.e. I called my role myusergroup instead of aw001\myusergroup. After correcting it, it worked fine.

When logging in with a domain user, an Orchard User is created. You do not see in the Orchard administration that this user has the role you’ve created (which is called the same as an Active Directory group) but when considering the roles of the user for checking the permissions, now Orchard will use both the roles assigned in Orchard and the groups assigned to the user in the Active Directory. Great !

 

Orchard CMS: Package uploading and installation failed

You may get an error message like this when installing a new theme or module in Orchard CMS:

Package uploading and installation failed

There are a few things you need to check to find out what the problem is, make sure that:

  • your ApplicationPool is using the .NET Framework Version 4.0 and an Integrated Managed Pipeline Mode.
  • the ApplicationPool Identity is set to ApplicationPoolIdentity
  • the user your web server process is running under has write access to the Modules, Themes and App_Data directories.

For the last point, you can find out the user by opening the task manager, showing processes for all users and checking the User Name for IIS Worker Process (e.g. w3wp.exe). Then give this user write access to the three folders mentioned above.

Orchard CMS: Exporting and Importing custom content types

Orchard CMS provides a nice module to import and export content items. You just need to enable the module called “Import Export”. This will add a menu item in the left navigation sidebar. There you can export all content items of given types. This will create an XML file containing all exported content items. It also provides an import function where you can choose an exported XML file and have it imported.

In Orchard CMS cloning is using the same infrastructure as import/export. So please first read my previous post about cloning content items in Orchard CMS.

Once you’ve added the Importing and the Exporting methods to your driver, you might see that the export file looks like this:

<!--Exported from Orchard-->
<Orchard>
  <Recipe>
    <Name>Generated by Orchard.ImportExport</Name>
    <Author>admin</Author>
    <ExportUtc>2014-04-19T14:28:24.7757008Z</ExportUtc>
  </Recipe>
  <Data>
    <MyCustomType Id="" Status="Draft">
      <CommonPart Owner="/User.UserName=admin" CreatedUtc="2014-04-17T09:23:30Z" ModifiedUtc="2014-04-17T09:23:30Z" />
      <MyCustomTypePart Name="My name is..." />
    </MyCustomType>
  </Data>
</Orchard>

And when you import this, nothing happens (and the log files contain no error). If it is the case, you have the same problem I had and there is an easy fix.

The problem is that the export file contains an empty ID for all content items. Actually you should have an ID in there starting with /Identifier= and followed by a unique ID. In order to fix it, you need to add an IdentityPart to your content type. Here’s what the Orchard documentation says about the IdentityPart:

The Identity part is useful to provide a unique identity to a content item that doesn’t have a natural one. For example, pages are naturally identified by their relative URL within the site, or users by their user name, but widgets have no such natural identity. In order to enable importing and exporting of those items, the identity part can be added. It creates GUIDs that are used as a unique identity that can reliably be exchanged between instances of Orchard.

So you just need to add this part to your content item. You can either add it in the Admin UI or add an Update method to your Migrations.cs file e.g.:

[UsedImplicitly]
public int UpdateFrom19()
{
	ContentDefinitionManager.AlterTypeDefinition("MyCustomType", cfg => cfg.WithPart("IdentityPart"));

	return 20;
}

Now the export file will look like this:

<!--Exported from Orchard-->
<Orchard>
    <Recipe>
        <Name>Generated by Orchard.ImportExport</Name>
        <Author>admin</Author>
        <ExportUtc>2014-04-19T14:47:34.3426219Z</ExportUtc>
    </Recipe>
    <Data>
        <MyCustomType Id="/Identifier=defe165123124b20a7fcb35e66873fbf" Status="Draft"> 
            <IdentityPart Identifier="defe165123124b20a7fcb35e66873fbf" /> 
            <CommonPart Owner="/User.UserName=admin" CreatedUtc="2014-04-17T09:23:30Z" ModifiedUtc="2014-04-17T09:23:30Z" />
            <MyCustomTypePart Name="My name is..." />
        </MyCustomType>
    </Data>
</Orchard>

 

And the import will work…

 

 

Orchard CMS: Cloning custom content items

When listing instances of a custom content item type, you will see that next to the Preview, Publish, Edit and Delete operations, there is also a Clone operation.
clone operation
When using it on a custom content item, you will also see that it’s merely creating an empty content item, not taking over any of the actual data.
Unfortunately, in all tutorials about custom content items I have read, I haven’t seen anything pointing to how to make Orchard actually create a real copy of the selected content item.

It’s actually pretty simple. The ContentPartDriver class your driver is extending, contains a bunch of methods for importing and exporting:

protected virtual void Importing(TContent part, ImportContentContext context) {}
protected virtual void Imported(TContent part, ImportContentContext context) {}
protected virtual void Exporting(TContent part, ExportContentContext context) {}
protected virtual void Exported(TContent part, ExportContentContext context) {}

All you have to do is override the methods Importing and Exporting in your driver:

protected override void Importing(MyCustomQueryPart part, ImportContentContext context)
{
}

protected override void Exporting(MyCustomQueryPart part, ExportContentContext context)
{
}

Exporting will be called when the content part is exported. You have to map the properties from the content part to XML attributes.
Importing will be called when importing a content part. You have to map back the XML attributes to content part properties.

For example:

protected override void Importing(MyCustomQueryPart part, ImportContentContext context)
{
	string name = context.Attribute(part.PartDefinition.Name, "Name");
	if (name != null)
	{
		part.Name = name;
	}
}

protected override void Exporting(MyCustomQueryPart part, ExportContentContext context)
{
	context.Element(part.PartDefinition.Name).SetAttributeValue("Name", part.Name);
}

Note that if your properties are not strings you’ll have to convert them in the importing using e.g. bool.Parse or int.Parse e.g.:

protected override void Importing(MyCustomQueryPart part, ImportContentContext context)
{
	part.IsOk= bool.Parse(context.Attribute(part.PartDefinition.Name, "IsOk"));
}

In the exporter, the conversion to strings is done automatically using ToString().

That’s it. Now your content part can be imported and exported and it can be cloned as well !

Now if one of the properties is actually a reference to a different content part, you’ll have to map in the importer the id to a content part e.g.:

int referenceId = int.Parse(context.Attribute(part.PartDefinition.Name, "Reference"));
part.Reference = _otherContentService.GetOtherContentPart(referenceId);

And you of course need to inject the service in the constructor of your driver:

private readonly ILinqFileService _fileService;

public MyCustomDriver(IOtherContentService otherContentService)
{
	_otherContentService = otherContentService;
}

And define GetOtherContentPart in IOtherContentService and implement it in the service itself e.g.:

public ContentItem GetOtherContentPart(int referenceId)
{
	return _contentManager.Get(referenceId, VersionOptions.AllVersions);
}

_contentManager is also injected in the Service by defining it in the constructor:

private readonly IContentManager _contentManager;

public OtherContentService(IContentManager contentManager)
{
	_contentManager = contentManager;
}

It’s a little bit more complex but I guess you’ll need the GetOtherContentPart method for other purposes anyway (I already had it in there).

So the conclusion is that Orchard provides pretty much everything you need in a nicely designed way but unfortunately the lack of documentation makes it very difficult to figure out how to use it. In such cases (as always with Orchard) your best starting point is the source code of existing modules and search engines (although Orchard being relatively new, you will not find everything in search engines).

NHibernate: NullReferenceException on bitwise operations in the where clause

When performing a bitwise operations in the where clause of a LINQ query using the NHibernate LINQ provider e.g.:

from o in SomeObjects where (o.SomeFlags & myBitMask) != myBitMask

you might geht the following exception:

System.NullReferenceException: Object reference not set to an instance of an object.
   at NHibernate.Criterion.SubqueryExpression..ctor(String op, String quantifier, DetachedCriteria dc, Boolean prefixOp) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Criterion\SubqueryExpression.cs:line 30
   at NHibernate.Criterion.Subqueries.Eq(Object value, DetachedCriteria dc) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Criterion\Subqueries.cs:line 130
   at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitBinaryCriterionExpression(BinaryExpression expr)
   at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitBinary(BinaryExpression expr)
   at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
   at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitOrElseExpression(BinaryExpression expr)
   at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitBinary(BinaryExpression expr)
   at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
   at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitAndAlsoExpression(BinaryExpression expr)
   at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitBinary(BinaryExpression expr)
   at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
   at NHibernate.Linq.Visitors.ExpressionVisitor.VisitLambda(LambdaExpression lambda)
   at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
   at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitUnary(UnaryExpression expr)
   at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
   at NHibernate.Linq.Visitors.RootVisitor.HandleWhereCall(MethodCallExpression call)
   at NHibernate.Linq.Visitors.RootVisitor.VisitMethodCall(MethodCallExpression expr)
   at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
   at NHibernate.Linq.Visitors.NHibernateQueryTranslator.Translate(Expression expression, QueryOptions queryOptions)

I actually even got this exception with a much simpler query:

query
	.Where(
		q =>
			(q.QueryType == null || q.QueryType != xxx) &&
			(q.Variables == null || q.Variables.Trim().Length == 0));

This is due to a bug in NHibernate which seems to be solved in the newer versions of NHibernate. Unfortunately, since I’m using Orchard CMS moving to a newer version of NHibernate is not an option. But the solution is quite simple: You need to convert the query object to a list first and then perform the Where operation. Like this you basically do not rely on any NHibernate class and can workaround the bug:

IEnumerable<LinqQueryPart> query = zzz.List<LinqQueryPart>();
return
	query
		.Where(
			q =>
				(q.QueryType == null || q.QueryType != xxx) &&
				(q.Variables == null || q.Variables.Trim().Length == 0));

Orchard: Association references unmapped class: System.String

After making some changes in one of my modules, I started getting the following error whenever I opened Orchard CMS in a browser:

Server Error in ‘/orchard’ Application.


Association references unmapped class: System.String

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: NHibernate.MappingException: Association references unmapped class: System.String

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[MappingException: Association references unmapped class: System.String]

NHibernate.Cfg.XmlHbmBinding.CollectionBinder.BindCollectionSecondPass(ICollectionPropertiesMapping collectionMapping, Collection model, IDictionary`2 persistentClasses, IDictionary`2 inheritedMetas) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Cfg\XmlHbmBinding\CollectionBinder.cs:741
NHibernate.Cfg.XmlHbmBinding.<>c__DisplayClass13.<AddCollectionSecondPass>b__12(IDictionary`2 persistentClasses) in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Cfg\XmlHbmBinding\CollectionBinder.cs:448
NHibernate.Cfg.Configuration.SecondPassCompile() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Cfg\Configuration.cs:1106
NHibernate.Cfg.Configuration.BuildSessionFactory() in c:\Users\sebros\Documents\My Projects\nhibernate-core\src\NHibernate\Cfg\Configuration.cs:1261
Orchard.Data.SessionFactoryHolder.BuildSessionFactory() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Data\SessionFactoryHolder.cs:91
Orchard.Data.SessionFactoryHolder.GetSessionFactory() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Data\SessionFactoryHolder.cs:69
Orchard.Data.SessionLocator.EnsureSession() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Data\SessionLocator.cs:109
Orchard.Data.SessionLocator.Demand() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Data\SessionLocator.cs:40
Orchard.Data.SessionLocator.For(Type entityType) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Data\SessionLocator.cs:34
Orchard.ContentManagement.DefaultContentManager.GetManyImplementation(QueryHints hints, Action`2 predicate) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\ContentManagement\DefaultContentManager.cs:326
Orchard.ContentManagement.DefaultContentManager.Get(Int32 id, VersionOptions options, QueryHints hints) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\ContentManagement\DefaultContentManager.cs:160
Orchard.ContentManagement.DefaultContentManager.Get(Int32 id, VersionOptions options) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\ContentManagement\DefaultContentManager.cs:131
Orchard.ContentManagement.DefaultContentManager.Get(Int32 id) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\ContentManagement\DefaultContentManager.cs:127
Orchard.Security.Providers.FormsAuthenticationService.GetAuthenticatedUser() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Security\Providers\FormsAuthenticationService.cs:110
Orchard.Security.CurrentUserWorkContext.<Get>b__0(WorkContext ctx) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Security\CurrentUserWorkContext.cs:13
Orchard.Environment.<>c__DisplayClass7`1.<FindResolverForState>b__5() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Environment\WorkContextImplementation.cs:37
Orchard.Environment.WorkContextImplementation.GetState(String name) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Environment\WorkContextImplementation.cs:28
Orchard.WorkContext.get_CurrentUser() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\WorkContext.cs:60
Orchard.Security.Authorizer.Authorize(Permission permission, IContent content, LocalizedString message) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Security\Authorizer.cs:72
Orchard.Security.Authorizer.Authorize(Permission permission) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Security\Authorizer.cs:60
Orchard.Exceptions.DefaultExceptionPolicy.RaiseNotification(Exception exception) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Exceptions\DefaultExceptionPolicy.cs:69
Orchard.Exceptions.DefaultExceptionPolicy.HandleException(Object sender, Exception exception) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Exceptions\DefaultExceptionPolicy.cs:44
Orchard.Events.DefaultOrchardEventBus.TryNotifyHandler(IEventHandler eventHandler, String messageName, String interfaceName, String methodName, IDictionary`2 eventData, IEnumerable& returnValue) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Events\DefaultOrchardEventBus.cs:56
Orchard.Events.<NotifyHandlers>d__0.MoveNext() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Events\DefaultOrchardEventBus.cs:41
System.Linq.Buffer`1..ctor(IEnumerable`1 source) +520
System.Linq.Enumerable.ToArray(IEnumerable`1 source) +103
Orchard.Events.DefaultOrchardEventBus.Notify(String messageName, IDictionary`2 eventData) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Events\DefaultOrchardEventBus.cs:27
Orchard.Environment.State.DefaultProcessingEngine.Execute(Entry entry) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Environment\State\DefaultProcessingEngine.cs:101
Orchard.Environment.State.DefaultProcessingEngine.ExecuteNextTask() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Environment\State\DefaultProcessingEngine.cs:67
Orchard.Environment.DefaultOrchardHost.EndRequest() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Environment\DefaultOrchardHost.cs:230
Orchard.Environment.DefaultOrchardHost.Orchard.Environment.IOrchardHost.EndRequest() in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Environment\DefaultOrchardHost.cs:82
Orchard.Web.MvcApplication.HostEndRequest(HttpApplication application, IOrchardHost host) in c:\svn\trunk\src\Apps\Orchard\src\Orchard.Web\Global.asax.cs:42
Orchard.WarmupStarter.Starter`1.OnEndRequest(HttpApplication application) in c:\svn\trunk\src\Apps\Orchard\src\Orchard.WarmupStarter\Starter.cs:75
Orchard.Web.MvcApplication.Application_EndRequest() in c:\svn\trunk\src\Apps\Orchard\src\Orchard.Web\Global.asax.cs:33

[TargetInvocationException: Exception has been thrown by the target of an invocation.]

System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +229
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +193
System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +35
System.Web.Util.ArglessEventHandlerProxy.Callback(Object sender, EventArgs e) +74
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18044

This error occured as soon as my module was enabled. Since it is an NHibernate exception I assumed it was caused either by a ContentPartRecord or by Migrations.cs. But I hadn’t changed anything in there. After searching for a root cause for a while (again, the exception didn’t help much in finding where the cause of the error could be found), I saw that I had created a class in the Models folder which had a property called Id. This class was neither ContentPartRecord nor referenced in Migrations.cs but I wondered whether the fact that Id is the default Identifier Property Name and it was indeed a string, maybe this was causing the problem. So I just renamed the property to something else and it solved my problem !

I am not too sure whether I only had this exception because the class was defined in the Models folder or whether it could have happened in any other folder. But I’m just not in the mood to try moving the class and renaming the property back to Id.

Orchard: Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.

After deploying Orchard CMS and filling out the setup form, I got the following error:

Server Error in ‘/orchard’ Application.


Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ObjectDisposedException: Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.

Source Error:

 

Line 23: @if (Model.Messages != null) {

Line 24: <div id=”messages”>

Line 25: @Display(Model.Messages)

Line 26: </div>

Line 27: }

Source File: c:\inetpub\wwwroot\orchard\Themes\SafeMode\Views\Layout.cshtml Line: 25

Stack Trace:

 

[ObjectDisposedException: Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.]

Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) in c:\Projects\OSS\autofac\Core\Source\Autofac\Core\Lifetime\LifetimeScope.cs:222

Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy.<>c__DisplayClass4.<CreateDelegate>b__3(DisplayContext context) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Descriptors\ShapeAttributeStrategy\ShapeAttributeBindingStrategy.cs:52

Orchard.DisplayManagement.Descriptors.<>c__DisplayClass5.<BoundAs>b__2(DisplayContext displayContext) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Descriptors\ShapeAlterationBuilder.cs:55

Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Process(ShapeBinding shapeBinding, IShape shape, DisplayContext context) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:179

Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Execute(DisplayContext context) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:88

Orchard.DisplayManagement.Implementation.DisplayHelper.ShapeExecute(Object shape) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:86

Orchard.DisplayManagement.Implementation.DisplayHelper.Invoke(String name, INamedEnumerable`1 parameters) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:44

Orchard.DisplayManagement.Implementation.DisplayHelper.TryInvoke(InvokeBinder binder, Object[] args, Object& result) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:29

CallSite.Target(Closure , CallSite , Object , Object ) +220

System.Dynamic.UpdateDelegates.UpdateAndExecute2(CallSite site, T0 arg0, T1 arg1) +975

ASP._Page_Themes_SafeMode_Views_Layout_cshtml.Execute() in c:\inetpub\wwwroot\orchard\Themes\SafeMode\Views\Layout.cshtml:25

System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +280

System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +126

System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +196

System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData) +158

Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.ShapeTemplateBindingStrategy.Render(ShapeDescriptor shapeDescriptor, DisplayContext displayContext, HarvestShapeInfo harvestShapeInfo, HarvestShapeHit harvestShapeHit) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:142

Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy.<>c__DisplayClass28.<Discover>b__15(DisplayContext displayContext) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Descriptors\ShapeTemplateStrategy\ShapeTemplateBindingStrategy.cs:126

Orchard.DisplayManagement.Descriptors.<>c__DisplayClass5.<BoundAs>b__2(DisplayContext displayContext) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Descriptors\ShapeAlterationBuilder.cs:55

Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Process(ShapeBinding shapeBinding, IShape shape, DisplayContext context) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:179

Orchard.DisplayManagement.Implementation.DefaultDisplayManager.Execute(DisplayContext context) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DefaultDisplayManager.cs:88

Orchard.DisplayManagement.Implementation.DisplayHelper.ShapeExecute(Object shape) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:86

Orchard.DisplayManagement.Implementation.DisplayHelper.Invoke(String name, INamedEnumerable`1 parameters) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:44

Orchard.DisplayManagement.Implementation.DisplayHelper.TryInvoke(InvokeBinder binder, Object[] args, Object& result) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\DisplayManagement\Implementation\DisplayHelper.cs:29

CallSite.Target(Closure , CallSite , Object , Object ) +220

System.Dynamic.UpdateDelegates.UpdateAndExecute2(CallSite site, T0 arg0, T1 arg1) +975

Orchard.Mvc.ViewEngines.ThemeAwareness.<>c__DisplayClass7.<FindView>b__5(ViewContext viewContext, TextWriter writer, IViewDataContainer viewDataContainer) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Mvc\ViewEngines\ThemeAwareness\LayoutAwareViewEngine.cs:63

Orchard.Mvc.ViewEngines.ThemeAwareness.LayoutView.Render(ViewContext viewContext, TextWriter writer) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Mvc\ViewEngines\ThemeAwareness\LayoutAwareViewEngine.cs:90

System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +378

System.Web.Mvc.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17() +33

System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +854172

System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +854172

System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +854172

System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +854172

System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +854172

System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +265

System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +854224

System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__19() +40

System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +15

System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +65

System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15

System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +51

System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +42

System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15

System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +51

Orchard.Mvc.Routes.HttpAsyncHandler.EndProcessRequest(IAsyncResult result) in c:\svn\trunk\src\Apps\Orchard\src\Orchard\Mvc\Routes\ShellRoute.cs:159

System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606

System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288

 


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18044

Once again, the error message doesn’t really help much. The problem was actually that I had given full access rights for the DefaultAppPool user to the App_Data folder but not to the whole orchard folder.

Once I’ve given full rights to the whole folder:

Permissions for Orchard

and resent the form, everything worked fine.