You can also apply action filters to serialize only the interface properties if the return type of the controller method is an interface. This way you always stay in sync with your interface definition without having to change any attributes on the class implementing the interface.
For this you'd first have to create a custom InterfaceContractResolver
contract resolver as explained here:
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type _interfaceType;
public InterfaceContractResolver(Type interfaceType)
{
_interfaceType = interfaceType;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(_interfaceType, memberSerialization);
return properties;
}
}
Then add an action filter (either as an attribute as explained here or globally if you want this as a default behavior) that looks at the return type of the controller method and if it's an interface uses the contract resolver defined above:
public class InterfaceFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
if (content != null)
{
Type returnType = actionExecutedContext.ActionContext.ActionDescriptor.ReturnType;
if (returnType.IsInterface && content.Formatter is JsonMediaTypeFormatter)
{
var formatter = new JsonMediaTypeFormatter
{
SerializerSettings =
{
ContractResolver = new InterfaceContractResolver(returnType)
}
};
actionExecutedContext.Response.Content = new ObjectContent(content.ObjectType, content.Value, formatter);
}
}
}
}