I am trying to write a single macro method in Kentico (v8.2.x, or v9.0) that is cached appropriately, and exposes a POCO with a few public members.
Debugging in Visual Studio, I can see that the query is running fine, and an object instance is returned exactly how I want. Furthermore, inspecting the cached items using the Debug
application in Kentico also shows the full POCO instance data is cached as expected.
However, when invoking the macro, I only seem to be able to read my string representation of the object.
It is a macro that extends the CurrentUserInfo
type, so I am trying to invoke it like this:
{% CurrentUser.ClientStatus() %}
But attempts to retrieve any of the nested properties fails.
I am sure it is just that I have failed to do something (like register these properties correctly). But from the documentation, I have seen lots of things that it could be. For example:
Here is the macro itself:
/// <summary>
/// A class containing custom user-extension macros.
/// </summary>
[assembly: RegisterExtension(typeof(CustomUserMacros), typeof(CurrentUserInfo))]
public class CustomUserMacros : MacroMethodContainer
{
/// <summary>
/// Retrieves data regarding user client.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="parameters">The parameters.</param>
/// <returns>Data regarding user client information.</returns>
[MacroMethod(typeof(ClientInfo), "Retrieves client info.", 1)]
[MacroMethodParam(0, "user", typeof(CurrentUserInfo), "The user.")]
public static object ClientStatus(
EvaluationContext context,
params object[] parameters)
{
ClientInfo retVal = null;
if (parameters != null && parameters.Length > 0
&& parameters[0].GetType() == typeof(CurrentUserInfo))
{
var siteName = SiteContext.CurrentSiteName;
var userGuid = ((CurrentUserInfo)parameters[0]).UserGUID;
var uInfo = UserInfoProvider.GetUserInfoByGUID(userGuid);
retVal = CacheHelper.Cache(
cs => new ClientInfo(uInfo, siteName),
new CacheSettings(
60,
typeof(CustomUserMacros),
"ClientStatus",
userGuid));
}
return retVal;
}
}
And the ClientInfo
class is pretty straight-forward:
public class ClientInfo
{
public string Summary { get; private set; }
public CustomTableItem ClientRecord { get; private set; }
public IEnumerable<string> MediaPaths { get; private set; }
public ClientInfo(UserInfo userInfo, string siteCodeName) {
// ...
// Set properties, etc...
}
public override string ToString()
{
return Summary;
}
}
What is the easiest way for me to be able to access the properties, in a manner similar to the following?
{% CurrentUser.ClientStatus().ClientRecord["< Column Name >"] %}
To be able to access the properties in the way you describe, the parent object has to be of the DataRow
or DataRowView
type or implement one of the following interfaces: IVirtualHierarchicalObject
, IHierarchicalObject
, IDataContainer
, ISimpleDataContainer
.
In your case, ClientInfo
should implement IDataContainer
. The nested CustomTableItem
already implements one of the interfaces as it inherits from AbstractInfo
.
You'll have to implement several members which mainly work with a parameter called columnName
identifying the member whose value you should return:
public class ClientInfo : IDataContainer
{
...
public object GetValue(string columnName)
{
switch (columnName)
{
case "ClientRecord":
return ClientRecord;
case "Summary":
return Summary;
case "MediaPaths":
return MediaPaths;
}
return null;
}
...
}
Probably would not have worked in this case but worth noting as well that you can return simple object values using CMS.Base.DataContainer
or IEnumerable<CMS.Base.DataContainer>
:
return myCollection.Select(myObj => new DataContainer
{
["Value1"] = myObj.Value1,
["Value2"] = myObj.Value2
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With