I have a single selection ContentPicker field that contains a custom ContentType, which in turn contains multiple 'child' content types.
I can get to the single content type in the ContentPicker using the code below:
var contentPickerField = (ContentPickerField) Model.ContentField;
var customContentType = field.ContentItems.First();
However I can't find a way of accessing the 'child' ContentItems that are associated with that ContentType instance. For example:
myCustomItem.ContentItems.Count()
causes a null reference exception and Shape Tracing doesn't seem to deep enough to give me the query path.
Any help much appreciated and sorry in advance for the description - it's super hard to explain!
Related
I have a content type post where the entries have a categories attribute, which is an Array of Links (to a category content type).
I want to fetch all posts that have been tagged with a certain category. That is, Post entries where fields.categories[any link sys.id] = MyCategoryId.
I can only find an example only where the reference field is a singleton, not an array.
Would love any help, thanks!
You could specify your query like this:
/spaces/YOURSPACEID/entries?content_type=CONTENTTYPEID&fields.categories.sys.id=SOMEID
Notice that a content type restriction is necessary as we are filtering on a field property.
Also note that this only works because we're filtering on a system property directly accessible from the actual entry returned. If you wanted to filter on another property of the Category content type, for example title or description that is not currently supported.
Here's also a link to the official documentation including examples and explanations for the search api: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/query-entries
I have a content item called Event, which has a taxonomy field called Section attached via the content definition area.
What is the easiest way to retrieve the Section field from the content within an alternate? My alternate is not overriding an Event, so Model.ContentItem is not possible. Within my alternate my Event object instance is of type ContentItem which I am retrieving through the ContentManager.
This is what i'm doing at the moment:
ContentItem content = WorkContext.Resolve<IContentManager>().Get(id);
var = content.Parts.ElementAt(13).Fields.ElementAt(0);
I realise that in the above code the index's could change, the only other way I can think of doing this is by inserting Lambda expressions in the place of the integers.
content.Parts.ElementAt(13) returns object of type ContentPart
content.Parts.ElementAt(13).Fields.ElementAt(0) returns object of type TaxonomyField. Whereas I believe I need the TermPart?
If it cannot be achieved in a simple way, why is it so difficult to perform such a simple task?
Thank you in advance.
First you do not need the ContentManager on the template.
On the Model you have the ContentItem. You can retrive the field like this:
var contentItem = Model.ContentItem;
var terms = contentItem.Event.TaxonomyFieldName.Terms;
On terms you have the terms of the ContentItem.
I'm using Sharepoint 2010's web services interface to try to get the columns for a given list. I've got not problem with getting all of the columns using a GetList() call, but the issue is that I need to only get the columns that the user can see in the List Settings view of the Sharepoint UI.
The code that I'm currently using is as follows:
rootNode = serviceReference.GetList(List_id.ToString());
Element element = XElement.Parse(rootNode.OuterXml);
var fields = from e in element.Descendants()
where e.Name.LocalName == "Field" && e.Attribute("ID") != null &&
!(e.Attribute("Name").Value.StartsWith("_") && e.Attribute("SourceID").Value == "http://schemas.microsoft.com/sharepoint/v3")
select e;
Where serviceReference is an instance of the Sharepoint Lists Service and List_id is the GUID representing the list internally to Sharepoint.
This does filter out some of the columns that I don't want, but it doesn't get rid of everything.
Does anybody know what attributes I'm looking for to narrow it down just to the ones that the user can select to be added to a view? Or am I going about this entirely the wrong way?
Many thanks for any help.
The answer to this was that I was indeed looking in the wrong place for the information I needed. As user823959 pointed out, I needed to get the content type definition and use the fields in there rather than the list itself.
To do this was a two stage process, firstly we need to get the list of content types using the Lists.GetListContentTypes method (although this takes a content type id parameter, it doesn't actually seem to matter what we put here)
XmlNode rootNode = serviceReference.GetListContentTypes(List_id.ToString(), "0×01");
The CAML returned contains the definitions for each of the content types that are available in the list - with the first content type returned being the default one (in my case, the one I was after)
String contentType = rootNode.ChildNodes[0].Attributes["ID"].Value;
Once we've got the content type that we're after we can make a call to GetListContentType with the appropriate list content type id to get the full definition of the content type:
XmlNode contentTypeNode = serviceReference.GetListContentType(List_id.ToString(), contentType);
The CAML returned from this call will contain a list of field elements that correctly show the fields that are available in the SharePoint UI's view configuration. They can be selected in a LINQ query like this:
XElement contentTypesElement = XElement.Parse(contentTypeNode.OuterXml);
var fields = from e in contentTypesElement.Descendants()
where e.Name.LocalName == "Field"
select e;
At this point, we've got a list of Field XML elements that contain information about display names, static names, content types and a whole lot more. See Microsoft's documentation on the Lists.GetListContentType page for more information on the range of information returned about each field.
Many Thanks to user823959 for pointing me in the right direction.
I have a Content Type "News" with custom field "NewsDate" (DateTimeField) and "Active" (BooleanField)
Now I'm need to get 3 active atimes order desc by NewsDate
Get all news, make them toList() and from there manipulate the data is not a solution.
P.S. I need to do something like:
var items = contentManager
.Query(Entities[PageType.Press])
.OrderByDescending<CommonPartRecord, DateTime?>(record => record.PublishedUtc)
.Slice(0, 3);
but instead of PublishedUTC use my custom field "NewsDate" and add Active == true, However it is not possible due to Orchard architecture of storing custom data in a separate field as XML data.
UPDATED:
In a nutshell I want to generate from code behind the following Query:
DECLARE #temp as TABLE(id int, xmldata xml)
INSERT #temp VALUES(1,'<Data><News><NewsDate>07/14/2011 11:42:00</NewsDate><Link Title="" DisplayText="" Link="www.example.com" OpenInNewTab="True">www.example.com</Link></News></Data>')
INSERT #temp VALUES(2,'<Data><News><NewsDate>07/11/2011 12:11:00</NewsDate><Link Title="" DisplayText="" Link="www.example.com" OpenInNewTab="True">www.example.com</Link></News></Data>')
INSERT #temp VALUES(3,'<Data><News><NewsDate>02/21/2012 16:56:00</NewsDate><Link Title="" DisplayText="" Link="www.example.com" OpenInNewTab="True">www.example.com</Link><NewsLink></NewsLink></News></Data>')
SELECT
TOP 3 [id],
[xmldata].value('(Data/News/NewsDate)[1]', 'datetime') as NewsDate
FROM #temp
ORDER BY NewsDate DESC
P.S. I looked through the code for DynamicContentQueryTests, however all the examples uses the Part, and in my case Fields are just in the ContentItem:
E.g. News content type contains NewsDate field (datetime field) and some parts as well
Any suggestions are greatly appreciated.
Querying fields is possible since 1.4 through Projector and underlying index tables and new APIs on Content Manager. Your simplest bet actually may be to create a projection.
To get the values of fields that have been attached directly to a Content Item, you need to first look for the Content Part with the same name as the item, which is created by Orchard. So in your case in the Parts list for each News Content Item you'll find a part called "NewsPart", and inside this the Fields property will have your NewsDate and Active fields.
However, like you say Orchard serializes the field values into XML for storage to prevent it having to change the database structure every time you add/remove a field to/from a content type. For this reason, querying and ordering by fields is not recommended because all the serialized data needs to be de-serialized for each Content Item. If you want to be able to do this, the best way is to make your own Content Part with a Content Part Record and use your own table for storage, then you can do this:
contentManager.Query<NewsPart, NewsPartRecord>()...
...and query/sort on whatever values you like.
Bertrand is correct. Check this link : http://www.davidhayden.me/blog/projector-module-in-orchard-cms. You can implement your requirements easily with Projection Module. The link will tell you the steps to do that. If you don't want a widget, you can create a page with your query too. Once the module is enabled, you will see the option to create a Projection Page in the left hand side navigation.
EDIT :
Can't you simply parse the XML? You can query your content type 'News'. Something like -
var contentItems = contentManager.Query<ContentPart>("News").Join<TitlePartRecord>().Join<AutoroutePartRecord>().Join<CommonPartRecord>().List();
Once you have that, you can access the XML data by :
foreach (var item in contentItems)
{
var contentItem = (ContentItem)item.ContentItem;
ContentItemVersionRecord contentItemRecord = contentItem.VersionRecord;
string data = contentItemRecord.Data;
//Call some function here to parse 'data' and store the object in the list.
}
'data' has the information in XML format that you need.
You can parse it and then store the objects in your list that you can order by your custom field.
I got a question regarding content types and their IDs and how to use them with the object model.
First of all, I defined some site columns, a content type using these columns and a list definition using this content type via CAML. Each of the three components is realized as a feature. Another feature creates a list instance of this list definition.
So when I try to add a new item to the list using the my content type I use the following code.
SPListItem listItem = list.Items.Add();
SPContentType type = list.ContentTypes[new ContentTypeId("0x010044fb4458c2eb4800825910845a35554c")];
listItem["ContentTypeId"] = type.Id;
listItem["Title"] = "Titel";
listItem.Update();
When I execute this piece of code the type object is still null, also I'm sure the content type is attached to the list. Debugging the code and inspecting the list's content types shows me that the content type attached to the list doesn't have the id I defined in the content type definition (CAML). The id within the list instance is different but starts with the one I defined in the content type definition.
0x010044FB4458C2EB4800825910845A35554C0077D683BDD9969F4E920A27C334463321
So is this behavior normal? I expected the content type attached to the list to have the same id as in the definition.
My main goal is avoiding to use the name of the content type to retrieve it from the list's content types, but to use the unique id.
bye
Flo
When you create a list based on a content type, each instance of the list is actually a new content type that inherits from the parent.
Take a look at this...
http://soerennielsen.wordpress.com/2007/09/11/propagate-site-content-types-to-list-content-types/
Update-Regarding finding the instance of the List without using the name, take a look at the SPContentTypeUsage class also!
Don't stress too much about coding the Content Type's name as a constant within your code. While at first glance it may seem that it is possible to change the name of the content type, it should be regarded as a constant because the implications of changing the content type's name are non-trivial enough to demand a full build and re-release of your solution, allowing a change of the coded constant.
The ContentTypeID on the list is the ContentTypeID + the list ID.
The following code should do the trick:
//i try and keep these in a string constants class to avoid
//having to manage "magic strings" throughout my solution
SPContentTypeID ctid = new ContentTypeId("0x010044fb4458c2eb4800825910845a35554c");
//here's the magic
SPContentTypeID listCTID = list.ContentTypes.BestMatch(ctid);
//retrieve the ContentType with the appropriate ID
SPContentType type = list.ContentTypes[listCTID];
//do your thing
SPListItem listItem = list.Items.Add();
listItem["ContentTypeId"] = type.Id;
listItem["Title"] = "Titel";
listItem.Update();