[Development] WebApi Orchard expose objects from a list

Topics: Customizing Orchard
May 23, 2013 at 3:02 PM
Edited May 23, 2013 at 3:23 PM
Hi,

I try to figure out how to use WebApi in Orchard, and it works
http://www.davidhayden.me/blog/orchard-cms-and-asp.net-web-api
http://sebastienros.com/web-api-makes-it-in-orchard

But I don't know how to realize the subject below

I create a view with a list of object BookReview.
My assumption was the webApi is by default supported and any list is exposed.
But after to read the two topics, it's not the case, I need to add a module to manage it. (So I need to investigate how to request the datasource to get my list of BookReview).

[UPDATE]
I find in the documentation http://docs.orchardproject.net/Documentation/Content-types
But it's related to a part and not a contentType.
var items = _contentManager.Query<TitlePart, TitlePartRecord>()
    .Where(t => t.Title.Contains("foo"))
    .OrderBy(r => r.Title)
    .Slice(10, 5);
Am I right?
Developer
May 23, 2013 at 3:48 PM
Yes, to leverage WebApi, you need to write your own module that exposes an API that returns your list.
To query a list of BookReview, use the _contentManager as you did in your code snippet. Even though it seems to return a list of parts, it actually returns a list of content items, "casted" to the specified part. Parts don't live on their own: they are attached to a content item, which you can access like: myPart.ContentItem.

IContentManager.Query contains overloads that accepts the name of a content type. From the top of my head:
var items = _contentManager.Query<TitlePart, TitlePartRecord>("BookReview") ...
Pro tip: come join as at the upcoming Orchard Harvest in Amsterdam and learn from the people behind Orchard.
May 23, 2013 at 5:10 PM
Edited May 23, 2013 at 5:10 PM
Hi,

I try many things
_contentManager.Query<TitlePart, TitlePartRecord>("BookReview").Count()
_contentManager.Query("BookReview").Count()

BookReview isn't created by a module, it was created by the graphic administration.
I obtain a count equal to 3, it's correct.
In the viewer of debugger, I can't do .List() directly => "All thread must be finished to convert in to List"
I don't know how to obtain the object until I add the instruction _contentManager.Query<TitlePart, TitlePartRecord>("BookReview").List();
So I obtain information about the Title very good but how to return a list of BookReview, I try to use the code below, i obtain the issue
"Type 'Orchard.ContentManagement.DefaultContentManager' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types."
        public HttpResponseMessage Get() {
            try
            {
                HttpResponseMessage hrm = new HttpResponseMessage();
                return Request.CreateResponse(HttpStatusCode.OK,_contentManager.Query<TitlePart, TitlePartRecord>("BookReview").List());                
            }
            catch (Exception ex)
            {                
                throw ex;
            }
        } 
 public HttpResponseMessage Get() {
            try
            {
                HttpResponseMessage hrm = new HttpResponseMessage();
                var elementsToReturn = _contentManager.Query<TitlePart, TitlePartRecord>("BookReview").List();
                return Request.CreateResponse(HttpStatusCode.OK, elementsToReturn);                
            }
            catch (Exception ex)
            {                
                throw ex;
            }
        } 
And thank you about the tip, nevertheless I am not able to come :(
Developer
May 23, 2013 at 6:43 PM
Could you try this...

var elementsToReturn = _contentManager.Query<TitlePart, TitlePartRecord>("BookReview").List().ToList();

List() is an NHib thing.
May 24, 2013 at 7:30 AM
Edited May 24, 2013 at 9:45 AM
Hi,

1\I try to change by your proposal
public HttpResponseMessage Get() {
            try
            {
                HttpResponseMessage hrm = new HttpResponseMessage();
                var elementsToReturn = _contentManager.Query<TitlePart, TitlePartRecord>("BookReview").List().ToList();
                return Request.CreateResponse(HttpStatusCode.OK, elementsToReturn);                
            }
            catch (Exception ex)
            {                
                throw ex;
            }
        } 
I obtain the issue

Type 'Orchard.ContentManagement.DefaultContentManager' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.


2\ I try to change the signature.
  public List<TitlePart> Get() {
            try
            {
                HttpResponseMessage hrm = new HttpResponseMessage();
                return _contentManager.Query<TitlePart, TitlePartRecord>("BookReview").List().ToList();
                //return Request.CreateResponse(HttpStatusCode.OK, elementsToReturn);                
            }
            catch (Exception ex)
            {                
                throw ex;
           
I obtain the issue
Type 'Orchard.ContentManagement.DefaultContentManager' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.


3\ If I work with a intermediate class, [it works]. do you have other proposal?
 public class TitleElement
    {
        public String name;
    }

    public List<TitleElement> Get() {
        try
        {
            List<TitleElement> listElements = new List<TitleElement>();
            HttpResponseMessage hrm = new HttpResponseMessage();
            var elements = _contentManager.Query<TitlePart, TitlePartRecord>("BookReview").List().ToList();
            listElements.Add(new TitleElement(){ name= elements[0].Title});
            return listElements;
            //return Request.CreateResponse(HttpStatusCode.OK, elementsToReturn);                
        }
        catch (Exception ex)
        {                
            throw ex;
        }
    } 
Developer
May 25, 2013 at 1:02 AM
No, working with the intermediate class, or better known as Data Transfer Object (DTO) is a good way to go. Orchard's content items are not serializable, as you've seen: they reference other, non-serializable objects such as the content manager service object. Alternatively I think you could construct a JSON object and return that.
May 27, 2013 at 6:38 AM
Thank for your advice.