ContentResultService is executed instead of the injected one

Vote:
 

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 

 private readonly ContentResultService _contentResultService;

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? 

#200946
Jan 31, 2019 13:33
Vote:
 
 [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 

#200948
Jan 31, 2019 14:04
Vote:
 

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.

#200949
Jan 31, 2019 14:13
Vote:
 

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

#200951
Jan 31, 2019 14:19
Vote:
 

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.

#200956
Edited, Jan 31, 2019 14:36
Vote:
 

You don't need 

context.ConfigurationComplete

Go straight to 

context.Services.AddSingleton<ContentResultService, CustomContentResultService>();
#200957
Jan 31, 2019 14:38
Vote:
 

Thx Quan, unfortunately nothing has changed. Still the base one is executed. 

#200958
Jan 31, 2019 14:43
Vote:
 

What do your IConfigurableModule and CustomContentResultService look like? 

#200961
Jan 31, 2019 15:10
Vote:
 

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) { }
    }

#200966
Jan 31, 2019 15:34
Vote:
 

Given it looks like an environment specific issue you could try some simple things like:

  • Clearing your temp ASP.net files
  • Setting optimizeCompilations="false" in web.config

David

#201037
Feb 02, 2019 22:16
Vote:
 

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).

#201038
Feb 03, 2019 12:35
Vote:
 

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:

#201039
Feb 03, 2019 12:36
Vote:
 

@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

#201050
Edited, Feb 04, 2019 9:59
Vote:
 

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/

#201051
Feb 04, 2019 10:06
Vote:
 

Thx I will take a look on that.

In case I would find the reason of my issue I will update the topic.

#201055
Feb 04, 2019 10:57
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.