Widget to pull list of Module records

Topics: Customizing Orchard, General, Troubleshooting, Writing modules
May 9, 2011 at 4:43 PM

I built a module to create an UrgentIssue content type. That went well and is all working. Now I've been trying for the past few days to build a widget that will show the current ones (based on some criteria to only pull active and approved items) as a bar in the Messages zone. 

I was initially trying to copy how the blog module shows recent posts as it seemed comparable, but I can't get it to show my data. I created a contentPart and contentPartRecord for the widget. I have a driver with a display method that pulls the list of current items (an Enumerable of UrgentIssueParts). The blog module driver also had some code to build a shape and return it from the method, which I attempted to adapt. There is a view (Widget-CurrentUrgentIssues.cshtml) that is displaying on my page.

The problem is that I can't get my list of UrgentIssues to get passed into the view. Model.ContentItems is always empty.

What is the recommended way of building a widget like this?

Here is my Display method:

protected override DriverResult Display(CurrentUrgentIssuesPart part, string displayType, dynamic shapeHelper)
	var issues = _contentManager.Query(VersionOptions.Published, "UrgentIssue")
		.Where<UrgentIssuePartRecord>(x => x.IsApproved == true && x.IsActive == true)
		.OrderByDescending(cr => cr.CreatedUtc).List<UrgentIssuePart>();
		//.Slice(0, part.Count)
		//.Select(ci => ci.As<UrgentIssuePart>());
	//.Where(cr => cr.Container == )))))

	var list = shapeHelper.List();
	list.AddRange(issues.Select(i => _contentManager.BuildDisplay(i, "Summary")));

	var issueList = shapeHelper.Parts_UrgentIssue_List(
		ContentPart: part,
		ContentItems: list);

	return ContentShape("Widget__CurrentUrgentIssues",
		() => shapeHelper.Widget__CurrentUrgentIssues(
			ContentItem: part.ContentItem,
			ContentItems: issueList));


<h2>all current issues this @Model.ContentItems.Count</h2>
@*@foreach (var issue in Model.ContentItems)

May 9, 2011 at 4:52 PM

It all looks fine. Have you verified that your query is actually returning any records?

May 9, 2011 at 5:02 PM

Yes. I've debugged and the 'issues' variable with the expected 2 items I have saved. The problem looks like it might come when it calls the BuildDisplay method, though I'm not sure since it returns proxy elements and I'm not sure what to look for when inspecting those elements.

I'm not sure if there's also something inherently wrong with passing a list into the ContentShape. I had just follow what was done in http://orchard.codeplex.com/discussions/256665 and was able to display data I passed into it, except if I passed in a list of items. Passing in an integer worked, but not a list. When I did and debugged, the list was empty when putting a breakpoint in the view. However, the ShapeTracer showed that it was filled.

May 9, 2011 at 7:33 PM

Ah - I see the problem now. What you're doing is the following:

- Creating a "List" shape and passing in the display shapes

- Creating a "Parts_UrgentIssue_List" shape, and passing in the first List you created

- Creating a "Widget__CurrentUrgentIssues" shape, and passing in the Parts_UrgentIssue_List shape.

So when you do @Display(Model.ContentItems), it's actually rendering Parts_UrgentIssue_List - which would be displayed by a Parts.UrgentIssue.List.cshtml template (do you have one of those?)

What you need to do is just get rid of that intermediary shape and pass the List you built directly into Widget__CurrentUrgentIssues.

May 9, 2011 at 8:36 PM

I got rid of the intermediary step but it still doesn't show up. I then added in the Parts.UrgentIssue.List.cshtml view and went back to how I had been doing it, but that didn't show up either (just put some static text in the view to see if it would show and it didn't).

I've also added an integer value to the Widget__CurrentUrgentIssues shape, but that won't even get rendered:

return ContentShape("Widget__CurrentUrgentIssues",
	() => shapeHelper.Widget__CurrentUrgentIssues(
		ContentItem: part.ContentItem,
		Count: 10,
		ContentItems: issues));

So it almost seems like (in standard MVC terms) the model isn't getting passed over to the view. Or I'm passing it over in the wrong way or something.

Any other thoughts? I could send over the whole module if that would help. I created it in basically a brand new setup of the db, so there should be no dependencies.

May 9, 2011 at 8:40 PM

I just also tried changing the return to:

return ContentShape("Parts_UrgentIssue_List", () => issueList);
...but the output didn't change at all. Which makes me think the return statement is somehow completely ignored. Does that sound right? Could something be overriding that return somehow?

May 10, 2011 at 12:25 AM

If nothing is showing it usually means there's an exception happening somewhere in the driver (these get caught silently). Step thru in debug and check exactly what's happening.

May 10, 2011 at 3:55 PM

I've been debugging all morning and haven't run into any silent exceptions. The only exception I've run into is "The operation is not valid for the state of the transaction.", which seemed to just be because transactions were expiring while I was debugging because it was taking me too long to step through everything.

The only thing I can notice that might be a problem is that when it generates the shapes with _contentManager.BuildDisplay(i, "Summary"), the shape.ContentItem appears to be null. Not sure if this should be or not.

Anything else I could try?