{"id":866,"date":"2010-11-22T22:05:13","date_gmt":"2010-11-22T21:05:13","guid":{"rendered":"http:\/\/www.itidea.nl\/?p=866"},"modified":"2015-09-08T20:34:31","modified_gmt":"2015-09-08T18:34:31","slug":"sharepoint-2010-custom-health-rule-to-check-if-the-solution-resource-timerjobs-are-enabled-when-the-sandboxed-code-service-is-started","status":"publish","type":"post","link":"https:\/\/www.itidea.nl\/index.php\/sharepoint-2010-custom-health-rule-to-check-if-the-solution-resource-timerjobs-are-enabled-when-the-sandboxed-code-service-is-started\/","title":{"rendered":"SharePoint 2010 Custom Health Rule to check if the Solution Resource timerjobs are enabled when the Sandboxed Code Service is started"},"content":{"rendered":"<p>To monitor additional items not by default set up in SharePoint, custom health analyzer rules can be defined. For example the sandboxed solutions can be monitored a little bit better than SharePoint default provides.<br \/>\nWhen the Microsoft SharePoint Foundation Sandboxed Code Service is started sandboxed solutions can be deployed and used. To monitor the resources consumed by the sandboxed solutions a couple of timerjobs do the work of measuring and collecting the consumed resources:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<ul>\n<li>Solution Daily Resource Usage Update<\/li>\n<li>Solution Resource Usage Log Processing<\/li>\n<li>Solution Resource Usage Update<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<p>Wouldn&#8217;t it be nice to be sure the timerjobs are running when the Sandboxed Code Service is running?<br \/>\nPlease continue reading on how to set this up.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<h3>Building the rule<\/h3>\n<p>To set up a health analyzer rule, start with an empty SharePoint project. Add a class and inherit from SPHealthAnalysisRule. This is the class for the rule definition.<br \/>\nThe class can also be inherited from SPRepairableHealthAnalysisRule. This means the rule can repair the problem. When using this the method Repair() has to be implemented as well.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<p>To define a rule some properties has to be overridden, like\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<ul>\n<li>Category &#8211; Health Analyzer Rule Definitions are grouped by Category in the default view.<\/li>\n<li>Summary &#8211; the title for the rule.<\/li>\n<li>Explanation &#8211; displayed in the Health Reports list when the rule fails.<\/li>\n<li>Remedy &#8211; displayed in the Health Reports list when the rule fails.<\/li>\n<li>ErrorLevel &#8211; severity of the failure of the rule.<\/li>\n<\/ul>\n<p>All rule definitions can be found in the rule definition list: Central Administration, Monitoring, Review rule definitions.<br \/>\nThe Health Reports list can be found in the Central Administration, Monitoring, Review problems and solutions.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<p>The rule can be scheduled by overriding the AutomaticExecutionParameters property. In the get accessor return a SPHealthAnalysisRuleAutomaticExecutionParameters object.<br \/>\nWhen you don&#8217;t override the property the rule can be scheduled manually by a farm administrator.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters\r\n{\r\n\u00a0\u00a0\u00a0 get\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 SPHealthAnalysisRuleAutomaticExecutionParameters parameter = new SPHealthAnalysisRuleAutomaticExecutionParameters();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 parameter.Schedule = SPHealthCheckSchedule.Hourly;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 parameter.Scope = SPHealthCheckScope.Any;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 parameter.RepairAutomatically = false;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 parameter.ServiceType = typeof(SPTimerService);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return parameter;\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<p>In the code above the rule is scheduled on an hourly basis and the scope is set to SPHealthCheckScope.Any. This means the rule will run on the first available computer with the specified service.\u00a0\u00a0<\/p>\n<p>The code that identifies the real problem is the Check() method. The Check() method returns the outcome of the check: SPHeathStatus.Failed or SPHealthStatus.Passed. When Failed is the outcome of the check the rule will be displayed in the Health Reports list.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\r\npublic override SPHealthCheckStatus Check()\r\n{\r\n\u00a0\u00a0\u00a0 jobTitleOfDisabledJobs.Clear();\u00a0\r\n\r\n\u00a0\u00a0\u00a0 SPUserCodeService userCodeService = SPUserCodeService.Local;\r\n\u00a0\u00a0\u00a0 if (userCodeService.IsEnabled)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 using (SPSite site = new SPSite(&quot;your_site_url&quot;))\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 switch (job.Title)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 case &quot;Solution Daily Resource Usage Update&quot;:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 AddJobTitle(job);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 case &quot;Solution Resource Usage Log Processing&quot;:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 AddJobTitle(job);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 case &quot;Solution Resource Usage Update&quot;:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 AddJobTitle(job);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 default:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (jobTitleOfDisabledJobs.Count != 0)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return SPHealthCheckStatus.Failed;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 return SPHealthCheckStatus.Passed;\r\n}\r\n\r\n<\/pre>\n<p>The above code first checks if the Sandboxes Code Service is started. If so, it checks if the timerjobs involved in measuring the resources consumed\u00a0by the solutions are enabled.<br \/>\nThe AddJobTitle() method adds the title(s) of the disabled job(s) to a generic list of strings:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate void AddJobTitle(SPJobDefinition job)\r\n{\r\n\u00a0\u00a0\u00a0 if (job.IsDisabled)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 jobTitleOfDisabledJobs.Add(job.Title);\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<p>This list is used at the Explanation property to inform the farm administrator exactly which job(s) aren&#8217;t enabled:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic override string Explanation\r\n{\r\n\u00a0\u00a0\u00a0 get\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 string jobTitles = string.Empty;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (int i = 0; i &lt; jobTitleOfDisabledJobs.Count; i++)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 jobTitles += jobTitleOfDisabledJobs&#x5B;i].ToString();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (i != jobTitleOfDisabledJobs.Count - 1)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 jobTitles += &quot; \/ &quot;;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return &quot;The Microsoft SharePoint Foundation Sandboxed Code Service is started, but not all the timerjobs are: &quot; + jobTitles;\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<h3>Deploy the rule<\/h3>\n<p>To deploy the rule add a feature, scope it to farm level, and an event receiver to the feature.<br \/>\nOverride the FeatureInstalled and FeatureUninstalling to register and unregister the rule:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic override void FeatureInstalled(SPFeatureReceiverProperties properties)\r\n{\r\n\u00a0\u00a0\u00a0 try\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Assembly currentAssembly = Assembly.GetExecutingAssembly();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IDictionary&lt;Type, Exception&gt; exceptions = SPHealthAnalyzer.RegisterRules(currentAssembly);\u00a0\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (exceptions != null)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (exceptions.Count == 0)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ok\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/something went wrong, take appropriate action\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 catch (Exception ex)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw new Exception(&quot;There was an error registering the health rule: &quot; + ex.Message);\r\n\u00a0\u00a0\u00a0 }\r\n}\u00a0\r\n\r\npublic override void FeatureUninstalling(SPFeatureReceiverProperties properties)\r\n{\r\n\u00a0\u00a0\u00a0 try\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Assembly currentAssembly = Assembly.GetExecutingAssembly();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IDictionary&lt;Type, Exception&gt; exceptions = SPHealthAnalyzer.UnregisterRules(currentAssembly);\u00a0\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (exceptions != null)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (exceptions.Count == 0)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ok\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/something went wrong, take appropriate action\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 catch (Exception ex)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 throw new Exception(&quot;There was an error removing the health rule: &quot; + ex.Message);\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<p>After the deployment, the rule can be found in the rule definition list: Central Administration, Monitoring, Review rule definitions. The default view at this list is showing all the defined rules EXCEPT the rules defined with the categoy System. Ofcourse it&#8217;s possible to create an additional view to show all the rules.\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<h3>Run and test the rule<\/h3>\n<p>The rule is now scheduled to run every hour. To speed things up select the rule and press Run Now. The timerjob which actually runs the Health Analyzer jobs, this is dependent of the schedule, is in this case Health Analysis Job (Hourly, Microsoft SharePoint Foundation Timer, Any Server). Make this timerjob also run now and check the Health Reports list.<br \/>\nCheck if the rule fails when enabling and disabling the sandbox timerjobs which are checked in the rule. Note that the Explanation of the rule changes when different sandbox timerjobs are disabled or enabled.<br \/>\nKeep in mind when debugging the rule that you\u00a0attach the debugger to the timer services: OWSTimer.exe process.<br \/>\n<a href=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2010\/11\/HealthAnalyzerRuleSandboxRelatedJobs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-878\" title=\"HealthAnalyzerRuleSandboxRelatedJobs\" src=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2010\/11\/HealthAnalyzerRuleSandboxRelatedJobs.png\" alt=\"\" width=\"624\" height=\"317\" srcset=\"https:\/\/www.itidea.nl\/wp-content\/uploads\/2010\/11\/HealthAnalyzerRuleSandboxRelatedJobs.png 624w, https:\/\/www.itidea.nl\/wp-content\/uploads\/2010\/11\/HealthAnalyzerRuleSandboxRelatedJobs-300x152.png 300w\" sizes=\"auto, (max-width: 624px) 100vw, 624px\" \/><\/a><\/p>\n<h3>Issues<\/h3>\n<h5>Register Assemly in GAC<\/h5>\n<p>When developing the rule the following error occurred in my environment:<br \/>\nError occurred in deployment step &#8216;Add Solution&#8217;: Health analyzer rule registration requires that the {0} assembly be registered in the global assembly cache.\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<p>The workaround for me was to adjust the Site URL property of the project before every deployment. I know it&#8217;s not a nice solution and likely not THE solution, but it worked for me and restarting several services and jobs didn&#8217;t do the trick unfortunately.\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<h5>Settings are not updated<\/h5>\n<p>If you change your mind on for example the category or explanation while developing it is possible that after the deployment of the solution with the changed items and the rule fails, the rule shows up at the &#8216;old&#8217; category or with the &#8216;old&#8217; explanation. This is one of the possible &#8216;issues&#8217; which can occur if you don&#8217;t restart the Timer Service Recyle timerjob. This job is like an iisreset, but for the timer service, it recycles the Timer Service to free resources.\u00a0<\/p>\n<h3>Summary<\/h3>\n<p>Health Analysis Rules are not that hard to program, except a few things to know, but can be really usefull to have an overview of issues at the farm.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>To monitor additional items not by default set up in SharePoint, custom health analyzer rules can be defined. For example the sandboxed solutions can be monitored a little bit better than SharePoint default provides. When the Microsoft SharePoint Foundation Sandboxed &#8230; <a class=\"more-link\" href=\"https:\/\/www.itidea.nl\/index.php\/sharepoint-2010-custom-health-rule-to-check-if-the-solution-resource-timerjobs-are-enabled-when-the-sandboxed-code-service-is-started\/\">Read More &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[20,42,6],"class_list":["post-866","post","type-post","status-publish","format-standard","hentry","category-sharepoint-2010","tag-c","tag-sharepoint-2010","tag-visual-studio"],"_links":{"self":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts\/866","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/comments?post=866"}],"version-history":[{"count":17,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts\/866\/revisions"}],"predecessor-version":[{"id":884,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/posts\/866\/revisions\/884"}],"wp:attachment":[{"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/media?parent=866"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/categories?post=866"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.itidea.nl\/index.php\/wp-json\/wp\/v2\/tags?post=866"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}