Find your content:

Search form

You are here

Having trouble getting the KnowledgeArticleViewStat for the KnowledgeArticle

 
Share

So I am trying to get the KnowledgeArticleViewStat for a specific KnowledgeArticle. I am using the KnowledgeArticleViewStat.ParentId to match it to the KnowledgeArticle.Id.

This is my controller:

global with sharing class Article_View {

    global Map<Id, String> results {
        get {
            KnowledgeArticleViewStat result;
            List<KnowledgeArticleViewStat> results = [SELECT NormalizedScore, Id, ParentId FROM KnowledgeArticleViewStat WHERE Channel='Csp'];
            Map<Id, String> article_views = new Map<Id, String>();
            for (Integer i = 0; i < results.size(); i++) {
                 article_views.put((results[i].get('ParentId')) , String.valueOf(((Decimal)results[i].get('NormalizedScore')).round()));
            }
            return article_views;
        } 
        set; 
    }
}

This is my Component:

<apex:component controller="Article_View" access="global">
<apex:attribute name="key" description="key for results" type="Id" required="false"/>

 <apex:variable value="{!results[key]}" var="results"/> 
<apex:componentBody />
</apex:component>

And this is the relevant part of my VisualForce Page:

<knowledge:articleList articleVar="article" categories="BoxToneVersion:All" sortBy="mostViewed" pageSize="5">
        <tr>
            <td>
                <c:Query_article_view key="{!article.id}">
                    <apex:variable value="{!results}" var="result"/>
                        {!result}
                </c:Query_article_view>
            </td>
        </tr>
</knowledge:articleList>

When I access my page, I get this error:

Map key kA1W00000004CMJ not found in map
Error is in expression '{!results[key]}' in component <apex:variable> in component c:query_article_view

So I decided to print out the Map my controller was returning and the {!article.id} to see what values are in it. The Map looked like this:

{kA1W00000004CMnKAM=0, 
 kA0W00000008PEmKAM=2, 
 kA1W00000004CMJKA2=100, 
 kA0W00000008OtFKAU=97, 
 kA0W00000008OvzKAE=0, 
 kA2W00000004CkuKAE=1, 
 kA0W00000008OwEKAU=0, 
 kA0W00000008P1yKAE=0, 
 kA0W00000008Ow4KAE=0, 
 kA0W00000008Ow9KAE=0}

While my {!article.id} was this: kA1W00000004CMJ. So why is the ArticleId only a fragment of the ParentId? How do I get these to match up?


Attribution to: Di Zou

Possible Suggestion/Solution #1

When you are binding map in to page, it requires that all possible ids should be available in map as key irrespective of whether map is rendered or not for that particular id. For those ids you can simply keep your map value empty.


Attribution to: Vikash Tiwary

Possible Suggestion/Solution #2

The Id fields in Salesforce can be 15 or 18 characters long. Usually in Apex you should be fine using the 15-char version (case sensitive). When Apex will compare 15 char Id to 18 char Id variable it should perform the proper matching as needed. If you're interested in digging up more here's a nice start and you can just search Google for "Salesforce 15 vs 18 id" ;)

I think in your case something stupid happens when you pass the Id to component. I think it'll be passed as string and then Visualforce will fail to match them (the different length "magic" only works with real Id variables). Usually Apex manages to get the variable types right but VF is somewhat retar... lacking, many times I've seen errors saying I've tried to format a Currency or String as a Date even though perfectly valid Currency value was passed...

Anyway. You could try several things to fix it (in random order, food for thought):

  • amend passed Id to 18 char version (boring and not too useful but you can look up algorithms or even use the linked one... There's also a CASESAFEID function for pure Visualforce fix before you dive deep to Apex)
  • chop off extra bits of ParentId as you build the map (in other words, make the Map<String,String> and use .substring(0,15) etc. To be consistent & safe whenever VF get's fixed you'd be best LEFT'ing the "key" variable too.
  • amend your query to include WHERE Channel='Csp' AND ParentId = :passedIdVariable (will force the platform to sort out the length differences and is less wasteful on resources too).
  • declare a controller variable "Id key;" so parameter can be properly assigned (look up assignTo in <apex:param> reference) and cast.

Attribution to: eyescream
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/3424

My Block Status

My Block Content