JSON ContractResolver created in every request issue - json

I have an .NET Core Web Api 2.1 app in which I only serialize the properties requested by the client.
Example: GET orders/1?select=Id,TotalAmount
Example: GET orders/1?select=Id,CustomerName,DeliveryAddress,Location,ZipCode
For that, the app creates an object in every request (Lifetime Scoped) to get the requested properties.
Then, I created Custom ContractResolver class that is instanciated in every request by a global IResultFilter:
public class SerializationFilter : IResultFilter
{
private readonly IApiQueryParameters _apiQueryParameters;
public SerializationFilter(IApiQueryParameters apiQueryParameters)
{
this._apiQueryParameters = apiQueryParameters;
}
public void OnResultExecuting(ResultExecutingContext context)
{
var objectResult = context.Result as ObjectResult;
if (objectResult != null)
{
var contractResolver = new SelectiveResourceContractResolver(this._apiQueryParameters);
var serializerSettings = new JsonSerializerSettings
{
ContractResolver = contractResolver
};
var jsonFormatter = new JsonOutputFormatter(
serializerSettings,
ArrayPool<char>.Shared);
objectResult.Formatters.Add(jsonFormatter);
}
}
}
Now, this works for the first request made after the app is online.
The second request creates the ContractResolver correctly, but the response is not correct. The returned serialized properties are not the ones requested by the client.
Debugging the code, I noticed that when the SelectiveResourceContractResolver is created, it access the constructor method right,
public SelectiveResourceContractResolver(IApiQueryParameters apiQueryParameters)
{
this._apiQueryParameters = apiQueryParameters;
}
Also, it runs the CreateProperty overriden method:
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
But in the second request, the CreatePropertyMethod is not run.
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize =
instance =>
{
...
};
return property;
}
The second time on, it justs executes the property.ShouldSerialize = instance => part. I think some sort of caching is done by the app, but the wierd thing is that the ContractResolver is created in every request (it´s not set globally in Startup.cs) when the filter is executed. Also, when I debug it in the second request, the property IApiQueryParameters in the ContractResolver has all the values of the first request and not from the second execution of the constructor.
What I´m missing here?

I'm assuming your SelectiveResourceContractResolver inherits from DefaultContractResolver.
DefaultContractResolver.ResolveContract, which is called internally during serialization, caches contracts in a static, thread-safe dictionary, so CreateContract (which in turn calls CreateProperty) will only be called once per type for as long as your WebAPI process runs.
This is because calling CreateContract is expensive, and not caching contracts will seriously impact serialisation performance.
If you only need to cache contracts per response, you can create your own instance cache in SelectiveResourceContractResolver and override ResolveContract to use your cache instead:
public class InstanceCachingContractResolver : DefaultContractResolver
{
private readonly Dictionary<Type, JsonContract> contractCache = new Dictionary<Type, JsonContract>();
public override JsonContract ResolveContract(Type type)
{
if (!contractCache.TryGetValue(type, out JsonContract contract))
{
contract = CreateContract(type);
contractCache.Add(type, contract);
}
return contract;
}
}

Related

Json.net contractResolver is failling

I have implemented the custom contract resolver to remove the some properties from serialized Json. Most of the time below code works but occasionally this code fails. Sometime it loops through the list and skips item I want to exclude which causing to appear that properties which I wanted to exclude.
class TestClass
{
public static void Test()
{
var objectToSerialise = //Coming from some WebAPI calls
string[] stringToSkip = {"skip1", "skip2"};
var settings = new JsonSerializerSettings
{
ContractResolver = new MyContractResolver(stringToSkip)
};
var json = JsonConvert.SerializeObject(objectToSerialise, settings);
}
}
public class MyContractResolver : DefaultContractResolver {
private string[] _skipthis;
public MyContractResolver(string[] skipthis)
{
_skipthis = skipthis;
}
private JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization){
var property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = (prop) =>{
return !(_skipthis.Where(n => property.PropertyName.Contains(n)).Any());
};
return property;
}
}
Can someone please suggest why this code is failing silently intermittently with out throwing any kind of exception?
Note that skipthis array is not modified outside this. I want to skip the property when property name exist or substring of propertyname exist in skipthis array.

AutoMapper - passing parameter to custom resolver weird behavior

Although I'm relatively new to AutoMapper I'm using it in a small project I'm developing. I've never had problems using it before but now I'm facing some weird behavior passing parameters to a Custom Resolver.
Here's the scenario: I get a list of messages from my repository and then map those to a frontend friendly version of it. Nothing fancy, just some normal mapping between objects. I have a field in that frontend object that tells if a certain user already voted for that message and that's what I'm using the Custom Resolver for (it's that second "ForMember"):
public List<SupportMessageUi> GetAllVisible(string userId)
{
Mapper.CreateMap<SupportMessage, SupportMessageUi>()
.ForMember(dest => dest.Votes,
opt => opt.ResolveUsing<SupportMessageVotesResolver>())
.ForMember(dest => dest.UserVoted,
opt => opt.ResolveUsing<SupportMessagesUserVotedResolver>()
.ConstructedBy(() => new SupportMessagesUserVotedResolver(userId)));
var messages = _unitOfWork.MessagesRepository.Get(m => m.Visible);
var messagesUi = Mapper.Map<List<SupportMessageUi>>(messages);
return messagesUi;
}
I'm calling this method on a web service and the problem is: the first time I call the webservice (using the webservice console) it all runs perfectly. For example, if I pass '555' as the userId I get to this method with the correct value:
And in the Custom Resolver the value was correctly passed to the constructor:
The results returned are correct. The problem comes next. The second time I call the service, passing a different argument ('666' this time) the argument that gets to the constructor of the Custom Resolver is the old one ('555'). Here's what I mean:
Right before mapping the objects we can see that the value passed to the constructor was correct ('666'):
But when it gets to the constructor of the Resolver the value is wrong, and is the old one ('555'):
All subsequent calls to the service use the original value in the Custom Resolver constructor ('555'), independently of the value I pass to the service (also happens if I make the call from another browser). If I shut down the server and relaunch it I can pass a new parameter (that will be used in all other calls until I shut it down again).
Any idea on why this is happening?
It's happening because AutoMapper.CreateMap is a static method, and only needs to be called once. With the CreateMap code in your web method, you're trying to call it every time you call that method on your web service. Since the web server process stays alive between calls (unless you restart it, like you said) then the static mappings stay in place. Hence, the necessity of calling AutoMapper.Reset, as you said in your answer.
But it's recommended that you put your mapping creation in AppStart or Global or a static constructor or whatever, so you only call it once. There are ways to call Map that allow you to pass in values, so you don't need to try to finesse things with the constructor of your ValueResolver.
Here's an example using a ValueResolver (note the change to implementing IValueResolver instead of inheriting ValueResolver<TSource, TDestination>):
[Test]
public void ValueTranslator_ExtraMapParameters()
{
const int multiplier = 2;
ValueTranslator translator = new ValueTranslator();
Mapper.AssertConfigurationIsValid();
ValueSource source = new ValueSource { Value = 4 };
ValueDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(8));
source = new ValueSource { Value = 5 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(10));
}
private class ValueTranslator
{
static ValueTranslator()
{
Mapper.CreateMap<ValueSource, ValueDest>()
.ForMember(dest => dest.Value, opt => opt.ResolveUsing<ValueResolver>().FromMember(src => src.Value));
}
public ValueDest Translate(ValueSource source, int multiplier)
{
return Mapper.Map<ValueDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class ValueResolver : IValueResolver
{
public ResolutionResult Resolve(ResolutionResult source)
{
return source.New((int)source.Value * (int)source.Context.Options.Items["multiplier"]);
}
}
}
private class ValueSource { public int Value { get; set; } }
private class ValueDest { public int Value { get; set; } }
And here's an example using a TypeConverter:
[Test]
public void TypeTranslator_ExtraMapParameters()
{
const int multiplier = 3;
TypeTranslator translator = new TypeTranslator();
Mapper.AssertConfigurationIsValid();
TypeSource source = new TypeSource { Value = 10 };
TypeDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(30));
source = new TypeSource { Value = 15 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(45));
}
private class TypeTranslator
{
static TypeTranslator()
{
Mapper.CreateMap<TypeSource, TypeDest>()
.ConvertUsing<TypeConverter>();
}
public TypeDest Translate(TypeSource source, int multiplier)
{
return Mapper.Map<TypeDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class TypeConverter : ITypeConverter<TypeSource, TypeDest>
{
public TypeDest Convert(ResolutionContext context)
{
TypeSource source = (TypeSource)context.SourceValue;
int multiplier = (int)context.Options.Items["multiplier"];
return new TypeDest { Value = source.Value * multiplier };
}
}
}
private class TypeSource { public int Value { get; set; } }
private class TypeDest { public int Value { get; set; } }
Answering myself: I was not using AutoMapper.Reset(). Once I did that everything started working properly.
Helpful reading: http://www.markhneedham.com/blog/2010/01/27/automapper-dont-forget-mapper-reset-at-the-start/

Newtonsoft json serializer returns empty object

Ok - I've been beating my head against this for a few of hours now. Time to ask for help.
I have just upgraded my Web application project to ASP.NET MVC 4 RC, and the new WebApi.
My web api method is now returning EMPTY json "{}" - even though my object is fully populated.
I have replace the serializer with my own MediaTypeFormatter that also calls the Newtonsoft Json serializer, just so I can hook in and see things working.
What I see is an object going in to the serializer, and coming out as "{}".
This USED to work before I upgraded.
This is my object
[Serializable]
public class Parameters
{
public string ApplicantName { get; set; }
}
And I am just calling:
var result = JsonConvert.SerializeObject(new Parameters(){ Name = "test" });
I get back
"{}"
Whats going on??
[EDIT]
Someone else having the same problem... after running through the Newtonsoft source code, I can see we're having the exact same problem from a recent change.
http://json.codeplex.com/discussions/357850
Ok - there have been numerous changes, which result is some pretty radical changes to the Json output. These changes also include how custom TypeConverters are applied.
I have written a basic resolver which (for us at least) causes the Newtonsoft serializer to behave more like a basic Serializable object serializer - i.e. serializes all PROPERTIES, and doesnt use custom TypeConverters...
/// <summary>
/// A resolver that will serialize all properties, and ignore custom TypeConverter attributes.
/// </summary>
public class SerializableContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
foreach (var p in properties)
p.Ignored = false;
return properties;
}
protected override Newtonsoft.Json.Serialization.JsonContract CreateContract(Type objectType)
{
var contract = base.CreateContract(objectType);
if (contract is Newtonsoft.Json.Serialization.JsonStringContract)
return CreateObjectContract(objectType);
return contract;
}
}
* REGISTRATION *
In your MvcApplication "Application_Start"...
GlobalConfiguration.Configuration.Formatters
.JsonFormatter.SerializerSettings.ContractResolver =
new SerializableContractResolver()
{
IgnoreSerializableAttribute = true
};

How can I do dependency injection into action filters in ASP.NET 4 RC WebAPI?

I'm using Windsor to manage IoC for my controllers in a WebAPI project. I've got a DependencyResolver working nicely to resolve controller dependencies, but now I'm looking to inject dependencies into a custom action filter I'm using to manage authentication.
I've looked into using a custom ActionInvoker but it's not clear from the interface that WebAPI is using how I would go about resolving property dependencies on the custom action filter attribute before it executes. Anyone have a good example of how to do this in the MVC 4 RC?
EDIT: I'm aware you can't do constructor injection on filters, because they're attributes and therefore instantiated by the .NET framework - but I'm hoping there's some point in the execution lifecycle that happens AFTER the filter is instantiated but BEFORE it gets executed, where I could run some custom code to enumerate across the filters' public properties and inject the necessary services.
Action filters are attributes. In .NET attribute the instantiation process is managed by the .NET runtime and you don't have control over it. So one possibility is to use Poor Man's Dependency Injection which I would personally advice you against.
Another possibility is to use a marker attribute:
public class MyActionFilterAttribute : Attribute
{
}
and then have the action filter using constructor injection:
public class MyActionFilter : ActionFilterAttribute
{
private readonly IFoo _foo;
public MyActionFilter(IFoo foo)
{
_foo = foo;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ActionDescriptor.GetCustomAttributes<MyActionFilterAttribute>().Any())
{
// The action is decorated with the marker attribute =>
// do something with _foo
}
}
}
and then register it as a global action filter in Application_Start:
IFoo foo = ....
GlobalConfiguration.Configuration.Filters.Add(new MyActionFilter(foo));
I had the same problem, but decided to go for the ServiceLocator (DependencyResolver.GetService) for this, as its in the framework it seems to me to be a valid approach
public class RequiresSessionAttribute :
ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var sessionService =
(ISessionService) actionContext
.ControllerContext.Configuration.DependencyResolver
.GetService(typeof (ISessionService));
var sessionId = HttpUtility
.ParseQueryString(actionContext.Request.RequestUri.Query)
.Get("sessionId");
if (sessionId == null
|| !sessionService.IsValid(sessionId))
throw new SessionException();
base.OnActionExecuting(actionContext);
}
}
and here is a test for this attribute, bit of a pain but possible
public class requires_sessionId
{
[Fact]
void can_call_action_with_session_id()
{
var context = GetContext("http://example.com/?sessionId=blaa");
var sut = new RequiresSessionAttribute();
Assert.DoesNotThrow(
() => sut.OnActionExecuting(context));
}
[Fact]
void can_not_call_action_without_session_id()
{
var context = GetContext("http://example.com/");
var sut = new RequiresSessionAttribute();
Assert.Throws<SessionException>(
() => sut.OnActionExecuting(context));
}
HttpActionContext GetContext(string url)
{
var sessionServiceMock = new Mock<ISessionService>();
sessionServiceMock
.Setup(x => x.IsValid(It.IsAny<string>()))
.Returns(true);
var dependancyResolverMock = new Mock<IDependencyResolver>();
dependancyResolverMock
.Setup(x => x.GetService(It.IsAny<Type>()))
.Returns(sessionServiceMock.Object);
var config = new HttpConfiguration
{
DependencyResolver = dependancyResolverMock.Object
};
var controllerContext = new HttpControllerContext
{
Configuration = config,
Request = new HttpRequestMessage(
HttpMethod.Get,
url)
};
return
new HttpActionContext
{
ControllerContext = controllerContext,
};
}
}

Intercepting explicit interface implementations with Castle Dynamic Proxy

I am having trouble getting Castle Dynamic Proxy to intercept methods that are explicit interface implementations. I read here http://kozmic.pl/category/dynamicproxy/ that it should be possible to do this.
Here are my classes;
internal interface IDomainInterface
{
string DomainMethod();
}
public class DomainClass : IDomainInterface
{
string IDomainInterface.DomainMethod()
{
return "not intercepted";
}
}
Here is my interceptor class;
public class DomainClassInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Method.Name == "DomainMethod")
invocation.ReturnValue = "intercepted";
else
invocation.Proceed();
}
}
And here is my test (which fails);
[TestClass]
public void can_intercept_explicit_interface_implementation()
{
// Create proxy
var generator = new ProxyGenerator();
var interceptor = new DomainClassInterceptor();
var proxy = (IDomainInterface)generator.CreateClassProxy(typeof(DomainClass), interceptor);
// Invoke proxy method
var result = proxy.DomainMethod();
// Check method was intercepted -- fails
Assert.AreEqual("intercepted", result);
}
In addition to not being able to intercept the explicit interface implementation, it also seems that I am not receiving a notification of a non-proxyable member.
Here is my proxy generation hook (which acts as a spy);
public class DomainClassProxyGenerationHook : IProxyGenerationHook
{
public int NonProxyableCount;
public void MethodsInspected() {}
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
{
NonProxyableCount++;
}
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
return true;
}
}
Here is my test (which again fails);
[TestMethod]
public void receive_notification_of_nonproxyable_explicit_interface_implementation()
{
// Create proxy with generation hook
var hook = new DomainClassProxyGenerationHook();
var options = new ProxyGenerationOptions(hook);
var generator = new ProxyGenerator();
var interceptor = new DomainClassInterceptor();
var proxy = (IDomainInterface)generator.CreateClassProxy(typeof(DomainClass), options, interceptor);
// Check that non-proxyable member notification was received -- fails
Assert.IsTrue(hook.NonProxyableCount > 0);
}
Has anyone had success in getting DP to intercept explicit interface implementations? If so, how?
You are creating a class proxy. Class proxy only intercepts virtual methods on the class, and an explicit implementation of an interface method in C# by definition is not virtual (since it's private).
If you want to intercept methods on the interface you need to explicitly tell DynamicProxy about it
var proxy = (IDomainInterface)generator.CreateClassProxy(typeof(DomainClass), new Type[] { typeof(IDomainInterface) }, interceptor);
Also your interface is marked as internal so made sure it's public for DynamicProxy (either make the interface public or add InternalsVisibleToAttribute).
With that your first test will pass, and the method will be intercepted.