[ServiceConfiguration(typeof(ContentResultService))]
this does not guarantee that your implementation will be registered after the default implementation. To make sure yours will be registered and override the default one, register it in a IConfigurableModule.ConfigureContainer instead
would recommend also to reject all the other implementations (if that's the "singleton" case) and then register your implementation in the way Quan mentioned.
Unless you have a good reason to eject all other implementations, I'd let them be. You never know if you might break a code somewhere that relies on a collection of ContentResultService
I already tried that:
context.ConfigurationComplete += (o, e) =>
{
context.Services.AddTransient<ContentResultService, CustomContentResultService>();
};
I also tried to intercept but result is the same.
When I'm debugging place where ContentResultService is used, it seems that my implementation is injected but the base one is used.
and when I step into
So as you can see from the call stack, my custom implementation is completely ignored. Again, my colleague executed the same code and everthing is fine. Super weird.
You don't need
context.ConfigurationComplete
Go straight to
context.Services.AddSingleton<ContentResultService, CustomContentResultService>();
Thx Quan, unfortunately nothing has changed. Still the base one is executed.
What do your IConfigurableModule and CustomContentResultService look like?
CustomContentResultService is taken from the documentation so,
CustomContentResultService.cs
[ServiceConfiguration(typeof(ContentResultService))]
public class CustomContentResultService : ContentResultService
{
public CustomContentResultService(IContentApiSerializer contentApiSerializer) : base(contentApiSerializer)
{
}
/// <summary>
/// Build string content from object use given serializer
/// (1) Only return needed fields to clients (2) Only applied for content api not search api
/// </summary>
public override StringContent BuildContent(object value)
{
var fields = System.Web.HttpContext.Current.Request.Params["fields"];
if (string.IsNullOrEmpty(fields) || !(value is ContentApiModel))
{
return base.BuildContent(value);
}
var returnedProperties = fields.Split(',');
var convertedObj = new ExpandoObject() as IDictionary<string, Object>;
Func<string[], string, bool> shouldIncludeProperty = (propertyList, property) =>
{
return propertyList.Any(prop => string.Equals(prop, property, StringComparison.InvariantCultureIgnoreCase));
};
foreach (var prop in value.GetType().GetProperties())
{
var propertyType = prop.PropertyType;
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
{
var propertyDataDict = prop.GetValue(value, null);
foreach (var item in propertyDataDict as IDictionary<string, object>)
{
if (!shouldIncludeProperty(returnedProperties, item.Key))
{
continue;
}
convertedObj.Add(item.Key, item.Value);
}
continue;
}
if (!shouldIncludeProperty(returnedProperties, prop.Name))
{
continue;
}
var propValues = prop.GetValue(value, null);
convertedObj.Add(prop.Name, propValues);
}
return base.BuildContent(convertedObj);
}
}
IConfigurableModule
[InitializableModule]
[ModuleDependency(typeof(ServiceContainerInitialization), typeof(ContentApiCmsInitialization))]
public class ContentApiInitialization : IConfigurableModule
{
public void ConfigureContainer(ServiceConfigurationContext context)
{
// Register the extended content model mapper to be able to provide custom models from content api
context.Services.Intercept<IContentModelMapper>((locator, defaultModelMapper) =>
new ExtendedContentModelMapper(
locator.GetInstance<IUrlResolver>(),
defaultModelMapper,
locator.GetInstance<ServiceAccessor<HttpContextBase>>(),
locator.GetInstance<IContentVersionRepository>()
)
);
// set minimumRoles to empty to allow anonymous calls (for visitors to view site in view mode)
context.Services.Configure<ContentApiConfiguration>(config =>
{
config.Default().SetMinimumRoles(string.Empty);
});
context.Services.AddSingleton<ContentResultService, CustomContentResultService>();
}
public void Initialize(InitializationEngine context) {}
public void Uninitialize(InitializationEngine context) { }
}
Given it looks like an environment specific issue you could try some simple things like:
David
what about is you remove `[ServiceConfiguration]` attribute? Also you can check what exactly you have registered in StructureMap container. Fastest way is either during breakpoint `container.WhatDoIHave()` or via EPiServer DeveloperTools (https://nuget.episerver.com/package/?id=EPiServer.DeveloperTools). Latter is on your own risk :) Recommend not to go in production with that tool installed (unless you really need it).
but as David said - if your fellows can execute code successfully, this is something with your env. good timing to ask for new laptop :troll:
@David I've already tried to remove project build files and \AppData\Local\Temp\Temporary ASP.NET Files
, also tried to disable optimizeCompilations
. Unfortunately result is the same :(
@valdis removing [ServiceConfiguration]
was also my first thought but it basically register my CustomService twice.
From registered services, in structure map I don't see anything that might cause the issue.
I'm not 100% sure that it is my env issue but as my colleague was able to run it without any problems then it seems so.
Unfortunately my laptop is quite new, in other case you are right, it would be a good opportunity to request a new one :)
Anyway, thx guys for your help
I don't see your custom provider to be injected in ServiceAccessor<T> plugin as well. I had similar issue back in days when looking for answer to one of the forum questions. This might give you maybe some hints - https://blog.tech-fellow.net/2014/04/03/pragmatic-problem-solving-answer-to-the-episerver-forum-question/
Thx I will take a look on that.
In case I would find the reason of my issue I will update the topic.
I'm strugling with super weird issue. I wanted to test an example from
https://world.episerver.com/documentation/developer-guides/content-delivery-api/how-to-customize-data-returned-to-clients
Unfortuantely my CustomContentResultService is not executed. Base ContentResultService is executed all the time. I've tried to debug
ContentApiResult.cs becasue ContentResultService is called from there. In debuger
seems to be an instance of my CustomContenrService which is expected. But for some reason it's not executed. I've asked my colleague to do the same with the same codebase and everything is working for him. How is this possible? Is there any cache or anything which might cause this issue?