C# Sitecore get inherited templates - c#

I'm trying to find all templates that inherit a particular template through code. I have the ID of the base template (Base Web Page), and I'm iterating through all of the template items in Sitecore looking for items that inherit Base Web Page.
foreach (var item in templateItems)
{
var baseTemplates = item.Template.BaseTemplates.ToList();
foreach (var baseTemplate in baseTemplates)
{
if (baseTemplate.ID == templateItem.ID)
{
inheritors.Add(item.ID.ToString());
}
}
}
However, item.Template.BaseTemplates gives me a list of the root level base templates; instead of giving me Base Web Page, it gives me the templates that Base Web Page inherits from (Advanced, Appearance, Help, etc)
Therefore I don't know if the item is actually inheriting Base Web Page or not.
Is there a method to get directly inherited templates? How can I find all templates that inherit Base Web Page?

The part item.Template in the
var baseTemplates = item.Template.BaseTemplates.ToList();
line is incorrect.
item.Template returns /sitecore/templates/System/Templates/Template here, so you're checking for a BaseTemplate of Template template always.
Your code should be:
foreach (var item in templateItems)
{
var baseTemplates = new TemplateItem(item).BaseTemplates.ToList();
foreach (var baseTemplate in baseTemplates)
{
if (baseTemplate.ID == templateItem.ID)
{
inheritors.Add(item.ID.ToString());
}
}
}
And the better approach may be using LinkDatabase to find all the referrers of your item which link from BaseTemplate field like that:
var links = Sitecore.Globals.LinkDatabase.GetItemReferrers(templateItem, false);
foreach (var link in links)
{
if (link.SourceFieldID == Sitecore.FieldIDs.BaseTemplate)
{
inheritors.Add(link.SourceItemID.ToString());
}
}

Related

Setting trigger type for PowerAutomate Webhook in JSON

I have been modifying the swashbuckle filters to add extensions to the endpoints for adding to power automate.
Tried creating a custom connector from the Json created but found that the trigger type was not set. I have checked through the microsoft documentation but there (and elsewhere) it seems the only advice is how to set through their front end.
Is there a way to set this programmatically or will I have to modify this using the front end tool after import?
Thanks.
I ended up by adding through a DocumentFilter as follows:
foreach (var pathItem in document.Paths)
{
if (pathItem.Key.Contains(TriggerEndpointNaming))
{
if (!pathItem.Key.Contains("tenantWebHookId"))
{
foreach (var operation in pathItem.Value.Operations)
{
if (operation.Value.OperationId != null && operation.Value.OperationId.Equals("ManageWebHookAsync"))
{
operation.Value.Extensions.Add("x-ms-trigger", new OpenApiString("single"));
}
}
}
}
}

Sitecore access layout definition programmatically

I want to access the layout definition of an item so that I can access the renderings added to the item, and then access the datasources attached to said renderings. I can't seem to find a way to do this. The best I could do is access the __renderings field but I then found out that this is going to access the original rendering definition item rather than the specific, datasourced instance stored in the Design Layout.
This is on Sitecore 7.5 MVC
If it helps, this is what I tried doing:
// Get the default device
DeviceRecords devices = item.Database.Resources.Devices;
DeviceItem defaultDevice = devices.GetAll().Where(d => d.Name.ToLower() == "default").First();
// Get the rendering references for the default device
Sitecore.Data.Fields.LayoutField layoutField = item.Fields["__renderings"];
Sitecore.Layouts.RenderingReference[] renderings = layoutField.GetReferences(defaultDevice);
// Get the required renderings
RenderingItem headerRenderingItem = null;
RenderingItem aboutRenderingItem = null;
foreach (var rendering in renderings)
{
if (rendering.Placeholder == "headerPlaceholder")
headerRenderingItem = rendering.RenderingItem;
else if (rendering.Placeholder == "/aboutSectionPlaceholder/textPlaceholder")
aboutRenderingItem = rendering.RenderingItem;
}
Assert.IsNotNull(headerRenderingItem, "no header rendering item found");
Assert.IsNotNull(aboutRenderingItem, "no about rendering item found");
// Get their datasources
ID headerDatasourceId = ID.Parse(headerRenderingItem.DataSource); // The datasource string is null as it is accessing the datasource definition item itself
ID aboutDatasourceId = ID.Parse(aboutRenderingItem.DataSource); // Same as above
The RenderingReference.RenderingItem refers to the rendering item in the /layout section. What you could do is use RenderingReference.Settings.Datasource.
So your code would look something like:
foreach (var rendering in renderings)
{
if (rendering.Placeholder == "headerPlaceholder")
headerRenderingDatasourceId = rendering.Settings.Datasource;
else if (rendering.Placeholder == "/aboutSectionPlaceholder/textPlaceholder")
aboutRenderingDatasourceId = rendering.Settings.Datasource;
}
Item headerRenderingDatasourceItem;
if (!string.IsNullOrEmpty(headerRenderingDatasourceId)
headerRenderingDatasourceItem = item.Database.GetItem(headerRenderingDatasourceId);

sitecore RSS caching

I have been working on implementing a custom RSS feed in sitecore 6.4. My custom behaviour is very limited, all i effectively wanted to is add a link for author (our author field is a reference field so we cannot use the built in author attribution).
I overrode RenderItem() on the PublicFeed class so that i could make use of my own implementation of the FeedRenderer class (where the author logic is housed). my approach follows this pattern outlined by John West for adding your own rendering behaviour:
public class MyPUblicFeed: PublicFeed
{
protected override SyndicationItem RenderItem(Item item)
{
Assert.ArgumentNotNull(item, "item");
Control rendererControl = FeedUtil.GetFeedRendering(item);
if (rendererControl == null)
{
return null;
}
using (new ContextItemSwitcher(item))
{
var myRenderer= rendererControl as MyFeedRenderer;
if (myRenderer!= null)
{
myRenderer.Database = SitecoreHelper.CurrentDatabase.Name;
return myRenderer.RenderItem();
}
var renderer = rendererControl as Sitecore.Web.UI.WebControls.FeedRenderer;
if (renderer != null)
{
renderer.Database = SitecoreHelper.CurrentDatabase.Name;
return renderer.RenderItem();
}
}
throw new InvalidOperationException("FeedRenderer rendering must be of Sitecore.Web.UI.WebControls.FeedRenderer type");
}
}
And now for my rendering class:
public class MyFeedRenderer: Sitecore.Web.UI.WebControls.FeedRenderer
{
public override SyndicationItem RenderItem()
{
Item item = base.GetItem();
var syndicationItem = base.RenderItem();
//unfortunately we have to parse params again :(
FeedRenderingParameters feedRenderingParameter = FeedRenderingParameters.Parse(base.Parameters);
AddAuthor(syndicationItem, item, feedRenderingParameter);
return syndicationItem;
}
private static void AddAuthor(SyndicationItem syndicationItem, Item item, FeedRenderingParameters feedRenderingParameter)
{
//clear out authors added by base class
syndicationItem.Authors.Clear();
//logic for adding author here
}
}
this all works great, outputting exactly what i want, but the caching element doesn't appear to be working. I have set the cacheable flag on the actual item itself with a timespan of 01:00:00. This didn't appear to work - if i put a breakpoint in either of the above classes it is hit everytime the feed is requested.
so then i tried to enable caching at a control level, turning caching on with VaryByData for the MyFeedRenderer rendering. alas this isn't working either, the breakpoint is hit every time.
Can anyone offer any advice on this matter? the documentation simply recommends turning it on on the actual feed item, not at the Rendering level, but neither seem to be working for me. Interestingly HTML caching is working elsewhere - is RSS also put into the HTML cache?
Thanks in advance,
Nick
-Ensure the Cacheable checkbox in the feed definition item is checked.
-Ensure that you have published the feed definition item.
-If you do not populate the Cache Duration field in the feed definition item, it should default to one day.
-Feeds appear to cache in Sitecore.Syndication.FeedManager.Cache rather than the site output cache. Inspect that cache object in the Visual Studio debugger after calling your feed, and then again after calling that feed a second time, to try to see if any records appear, and if multiple cache keys appear for the same feed. Investigate the Render() method; if PublicFeed.IsCacheable() returns false (depending on the Cacheable field in the feed definition item), PublicFeed.Render() does not cache.
-Ensure nothing else clears caches between your requests for the feed.
SDN forum thread: http://sdn.sitecore.net/forum/ShowPost.aspx?PostID=40591

Cannot foreach through data context

i want to compare through 2 information, one is user input and second is admin ID in database. in my project, i'm using WCF Ria. i did created one auto-generated Domain Service Class and the code to retrieve everything in tblAdmin was auto-generated. i load the data in this way ::
var context = new OrganizationContext();
var x = context.tblAdmins;
context.Load(context.GetTblAdminsQuery());
cb1.ItemsSource = x;
it can load in this way, but i cannot get the x.adminID with this. so i tried this ::
foreach (var admin in x)
{
cb1.Items.Add(admin.adminID);
}
but failed... may i know is that possible to dig through the data without foreach or is there something wrong in my code ??
Looks like the problem is that the context.Load call is asynchronous - to get the result you need to pass a callback and get your data there:
context.Load(context.GetTblAdminsQuery(), LoadCompleted, null);
and:
public void LoadCompleted(LoadOperation<YOUR_ENTITY_TYPE> op)
{
foreach(var item in op.Entities)
{
//item is your entity, you can get item.adminID
}
}

Generate resouce file (resx) from MVC model definition

I've got a bunch of models to localize and I'm looking for a way to keep my effort as small as possible :)
Essentially, I have a model classes where all properties(as needed) are decrated with the DisplayNameAttribute.
What I'd like to do is, build a tool which looks for a property on the class definition (e.g. "Views.Contact") and then generates (updates) the default resx file (e.g. "Views.Contact.resx"). This implementation would follow a convention over configuration approach.
Are there any tools/examples out there, which I've missed, which will make this job easier? Is there any framework (.NET4) support for this?
Easier than I thought. Here is my (improvable) code:
public void GenerateResx()
{
Type model = typeof(BuyCABModel);
List<Type> member = new List<Type>();
member.Add(typeof(RegisterModel));
member.Add(typeof(AddOpenAuthAccountModel));
member.Add(typeof(LoginModel));
CreateRes(member, "Views.Member.resx");
}
private void CreateRes(List<Type> models, string resxFile)
{
using (ResXResourceWriter writer = new ResXResourceWriter("c:\\temp\\"+resxFile))
{
foreach(Type model in models)
{
PropertyInfo[] ps= model.GetProperties();
foreach (PropertyInfo p in ps)
{
foreach (Attribute a in p.GetCustomAttributes(true))
{
if (a.GetType() == typeof(DisplayNameAttribute))
{
DisplayNameAttribute d = (DisplayNameAttribute)a;
writer.AddResource(p.Name + "_DisplayName", d.DisplayName);
}
else if (a.GetType() == typeof(DisplayAttribute))
{
DisplayAttribute d = (DisplayAttribute)a;
writer.AddResource(p.Name + "_DisplayName", d.Name);
}
}
}
}
writer.Generate();
writer.Close();
}
}
Tip: If you need the designer.cs code generated in Visual Studio just open the .resx in VS and toggle the Access Modifier DropDown

Categories

Resources