5

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?

1

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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.