OpenSocial server is built on top of WCF and when you have service without configuration it can get pretty ugly.
So lets start. First you need to implement your message, easiest way is to use BaseOpenSocialMessage it would look something like this.
In order to return your type of message you need to add some behaviors to the service. Code will look like this
public
class
OpenSocialServiceFactoryExt : OpenSocial.Service.OpenSocialServiceFactory
{
public
override
System.ServiceModel.ServiceHostBase CreateServiceHost(
string
constructorString, Uri[] baseAddresses)
{
var service =
base
.CreateServiceHost(constructorString, baseAddresses);
service.Description.Behaviors.Add(
new
OpenSocialBehaviorExt());
return
service;
}
}
public
class
OpenSocialBehaviorExt : System.ServiceModel.Description.IServiceBehavior
{
#region IServiceBehavior Members
public
void
AddBindingParameters(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<System.ServiceModel.Description.ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public
void
ApplyDispatchBehavior(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
foreach
(ServiceEndpoint endpoint
in
serviceHostBase.Description.Endpoints)
{
foreach
(OperationDescription operationDescription
in
endpoint.Contract.Operations)
{
if
(!operationDescription.Behaviors.Any(b => b
is
OpenSocialFormattingBehaviorExt))
operationDescription.Behaviors.Add(
new
OpenSocialFormattingBehaviorExt());
}
}
}
public
void
Validate(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
{
}
#endregion
}
public
class
OpenSocialFormattingBehaviorExt : IOperationBehavior
{
#region IOperationBehavior Members
public
void
AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public
void
ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
public
void
ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Formatter =
new
OpenSocialMessageFormatterExt(dispatchOperation.Action, dispatchOperation.Formatter);
}
public
void
Validate(OperationDescription operationDescription)
{
}
#endregion
}
public
class
OpenSocialMessageFormatterExt : IDispatchMessageFormatter
{
private
string
action =
null
;
private
IDispatchMessageFormatter innerDispatcher =
null
;
public
OpenSocialMessageFormatterExt(
string
action, IDispatchMessageFormatter innerDispatcher)
{
this
.action = action;
this
.innerDispatcher = innerDispatcher;
}
#region IDispatchMessageFormatter Members
public
void
DeserializeRequest(global::System.ServiceModel.Channels.Message message,
object
[] parameters)
{
WebOperationContext contex = WebOperationContext.Current;
if
(contex.IncomingRequest.ContentType ==
"application/my-content-type"
)
{
// Deserialize request
}
else
{
innerDispatcher.DeserializeRequest(message, parameters);
}
}
public
global::System.ServiceModel.Channels.Message SerializeReply(MessageVersion messageVersion,
object
[] parameters,
object
result)
{
WebOperationContext contex = WebOperationContext.Current;
string
format = (contex.IncomingRequest.UriTemplateMatch.QueryParameters[
"format"
] ?? String.Empty).ToLowerInvariant();
if
(format ==
"my-format"
)
{
return
new
MyMessageFormat(result);
}
else
{
return
innerDispatcher.SerializeReply(messageVersion, parameters, result);
}
}
#endregion
}
As you can see there is more than few lines of code. I'll try to explain it in short. First we need to override service factory so we can attach additional behaviors in our case we need to add only formatting behavior. Since each operation can support different formats we're attaching our formatter to each operation. You can attach only one formatter to operation so you must pass previous formatter instance in your formatter. In general you're looking if you can handle requested content type, if you can you create a message to send and you're done else you just pass it to previous formatter.
And last thing to do is to set your factory in svc file. Find OpenSocial.svc inside MonoX and change Factory property to point to your factory
Unfortunately OpenSocial service has stuck in 3.5 framework and it will not work on 4.0 framework. I've fixed all issues, but you'll need to use nightly build. Let me know if you need any additional information.