Cannot return a CollectionContext from a WCF RESTful service
In your Sitefinity Convention Assurance documentation regrading creation of WCF RESTful services (Sitefinity 4.0), you state:
For every OperationContract (web service method) that retrieves a collection of items, return an object of type CollectionContext<T>, where you pass the type of the resource as a generic argument.
When I try to return a CollectionContext I get the following error:
Telerik.Sitefinity.Web.Services.CollectionContext`1[InstaOrderOpenAccess.EsfManufacturer] cannot be serialized because it does not have a parameterless constructor.
This error makes sense as the CollectionContext object does not have a parameterless constructor.
How do I return a CollectionContext object in my WCF service?
Thanks
- Courtney
P.S. Your online SiteFinity 4.0 RC Developer's Guide that talks about each of the Client Binder Controls (where I thought i might find an answer to this in an example) has links to sample code that do not work:
http://www.sitefinity.com/40/help/developer-manual/a3c3e363-2b58-4ac6-8c6b-d3c05171cb87.html
Article sample code: (broken link)
http://sitefinity.com/4.0/help/CodeExamples/RadGridBinderRead.zip
Hello Courtney,
I am sorry that the documentation has been misleading.
The collection context does not need to have a constructor without parameters, as the family of DataContractSerialzier-s use FormatterServices.GetUninitializedObject when Type.GetConstructor( Type.EmptyTypes ) returns null/Nothing.
This exception could be caused when you are not using a WCF service or for some reason it does not use XmlObjectSerializer.
Here are some instructions on how to find out what's wrong:
1.
<%@ ServiceHost
2.
Language="C#"
3.
Debug="true"
4.
Service="Telerik.Sitefinity.Modules.News.Web.Services.NewsItemService"
5.
Factory="Telerik.Sitefinity.Web.Services.WcfHostFactory"
6.
%>
[ServiceContract(Namespace =
"ContentService"
)]
[AllowDynamicFields]
public
interface
IContentService<TContent, TContentViewModel>
where TContent : SfModel.Content
where TContentViewModel : ContentViewModelBase
[OperationContract]
[WebGet(UriTemplate =
"/?sortExpression=sortExpression&skip=skip&take=take&filter=filter&provider=providerName&workflowOperation=workflowOperation"
, ResponseFormat = WebMessageFormat.Json)]
CollectionContext<TContentViewModel> GetContentItems(
string
sortExpression,
int
skip,
int
take,
string
filter,
string
providerName,
string
workflowOperation);
/// <summary>
/// The WCF web service that is used to work with all types that inherit from base <see cref="Content"/>
/// class.
/// </summary>
[ServiceBehavior(IncludeExceptionDetailInFaults =
true
, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public
abstract
class
ContentServiceBase<TContent, TParentContent, TContentViewModel, TParentContentViewModel, TContentManager> : IContentService<TContent, TContentViewModel>
where TContent : Content
where TParentContent : Content
where TContentViewModel : ContentViewModelBase
where TParentContentViewModel : ContentViewModelBase
where TContentManager :
class
, IManager, IContentLifecycleManager<TContent>
/// <summary>
/// View model class for the <see cref="NewsItem"/> model.
/// </summary>
public
class
NewsItemViewModel : ContentViewModelBase
/// <summary>
/// Initializes a new instance of the <see cref="NewsItemViewModel"/> class.
/// </summary>
public
NewsItemViewModel()
:
base
()
If you haven't found the problem after completing those steps, here is what we will need to troubleshoot this for you:
Dido, thanks for your reply. I tried all of your suggestions but I still got the same error message:
Telerik.Sitefinity.Web.Services.CollectionContext`1[InstaOrderOpenAccess.TestManufacturer] cannot be serialized because it does not have a parameterless constructor.
After a lot of trial and error, we have discovered the source of the problem.
(Sorry I cannot seem to highlight my text like you were somehow able to!)
[ServiceContract]
public
interface
IManufacturerService
[OperationContract]
[WebHelp(Comment = "Get all test manufacturers"
)]
[WebGet(UriTemplate =
"/test/?sort=sort&skip=skip&take=take&filter=filter"
,
ResponseFormat = WebMessageFormat.Json)]
CollectionContext<TestManufacturer> GetTestManufacturers(
string
sort,
int
skip,
int
take,
string
filter);
[OperationContract] [XmlSerializerFormat()]
[WebHelp(Comment = "Get all test manufacturers")]
[WebGet(UriTemplate = "/test/xml/?sort=sort&skip=skip&take=take&filter=filter"
,
ResponseFormat = WebMessageFormat.Xml)]
CollectionContext<TestManufacturer> GetTestManufacturersInXml(
string
sort,
int
skip,
int
take,
string
filter);
[OperationContract] [WebGet(UriTemplate =
"/id"
, BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat =WebMessageFormat.Json)]
TestManufacturer GetManufacturer(
string
id);
[OperationContract]
[XmlSerializerFormat()]
[WebGet(UriTemplate = "/xml/id"
, BodyStyle =
WebMessageBodyStyle.Bare, ResponseFormat= WebMessageFormat.Xml)]
TestManufacturer GetManufacturerInXml(
string
id);
Hi Courtney,
Without having the code to "play with", I can only suggest that you do remove the XmlSerializerFormat attribute.
Also, I would like to emphasize that we support DataContract serialization only, and XmlSerializer is not exactly tested. They are slightly different and obviously use different serializers: