Quantcast
Channel: ASPNETWebStack Issue Tracker Rss Feed
Viewing all articles
Browse latest Browse all 7215

Closed Feature: More virtual extensibility to XmlMediaTypeFormatter and make it instance-type-aware [189]

$
0
0
I'm going to try and keep this brief - but it might be difficult.

In the project I'm writing at the moment, I've customised the XML formatter to correctly serialize an instance based on it's actual type rather than the method's return type - paralleling what the JSON.Net serialiser does; which fixes a bug with XML content for the following service:

interface IFoo{
string Bar { get; set; }
}

class Foo : IFoo {
public string Bar { get; set; }
}

public class ExampleController : ApiController
{
public IFoo GetExample(){
return new Foo() { Bar = "Hello World!" };
}
}

When executed as JSON content, you get a JSON representation of the Foo.

When executed as XML content, the operation fails because the DataContractSerializer expects Foo to be added as a known type.

This can be fixed by changing the return type of the method - however, in my current project this just isn't desirable; as it's a multi-tenant application where controllers can be overriden based on request hostname; and the actual return types of the underlying service operations only have to implement the interface - but could have many more members specific to their remote operation.

To fix this - I created an 'Ex' version of the formatter - that picks up some data added by an ActionFilter which is used by the programmer to state declaratively that XML serialization should consider the whole-object, not just the static return type. I attach that code.

You'll notice that I've had to use the GetPerRequestFormatterInstance for this purpose - which is not ideal. More on that in a moment.

This solution does not, nor can it, solve cases where an IEnumerable<IFoo> or IDictionary<string, IFoo> will be returned. Again, the JSON.Net serializer is quite happy with this scenario, whereas the XML one is not.

In this case, it would be necessary to customise the actual serializer instance that is constructed based on the instance of the enumerable being serialized - a simple dynamic implementation being to forward-scan an IEnumerable or IDictionary (although IDictionary can be treated as IEnumerable<KeyValuePair<TKey, TValue>>) looking for all instances whose actual types are different to the static type of the generic, and then adding those to a dynamic list of known types.

This cannot be done in the current codebase - the creation of the serializer is private. However, making it virtual won't help on it's own either, because the value to be serialized must also be passed.

Ideally we need to be able to override the serializer creation code - and have that receive not only the type to be constructed, but also the value AND a state value that can be built from the request's properties (perhaps the properties themselves, or even the request).

I know that the GetPerRequestFormatterInstance method goes some way to solving this - and that it is possible to override serializers through the SetSerializer method - but the former is a very inefficient solution where lots of types are involved - and the second is clumsy. They also do not allow us to handle the case of the enumerables, as I say.

I will look forward to any furhter thoughts on this. If I've missed something blindingly obvious, then do let me know!
Comments: Verified.

Viewing all articles
Browse latest Browse all 7215

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>