Developer forum

Forum » Development » Custom Global tag in XSLT

Custom Global tag in XSLT

Kim Pedersen
Reply

How can I insert my own global custom tag in a xslt template?

I can get it to work in a html template by inserting the tag <!--@Global:Recipes--> on a html template and the backend code looks like this.

 [Subscribe(Dynamicweb.Notifications.Standard.Page.OnOutput)]
    public class NotificationGlobalTags : NotificationSubscriber
    {

        public override void OnNotify(string notification, object[] args)
        {
            Dynamicweb.Templatev2.Template t = args[0] as Dynamicweb.Templatev2.Template;
           
            if (t == null) return;
            t.SetTag("Global:Recipes", getIngredients());
        }
 


When I call DwTemplateTags the new custom tag is not in the list, so how do I call it in a xslt template?

Replies

 
Morten Bengtson
Reply

You need to use the OnGlobalTags notification. Have a look here: http://developer.dynamicweb-cms.com/Forum.aspx?PID=48&ThreadID=26314

 

/Morten
 
Kim Pedersen
Reply
Okay thanks, I get the message 'Dynamicweb.Notifications.Standard.Page' does not contain a definition for 'OnGlobalTags'

The solution is running on DW version 19.2.1.3

Do you know from which version the OnGlobalTags is out?
 
Morten Bengtson
Reply
OnGlobalTags was added in version 19.2.0.0 and is available in 19.2.1.3
Check your reference to Dynamicweb.dll and make sure it is the right one.

/Morten
 
Nicolai Høeg Pedersen
Reply
OnGlobalTags was added february 21st - in 19.2.1.0

 
Kim Pedersen
Reply
Now I can use my new global tag in XSLT, but unfortunately it seems that you can not use Database.getDataReader (..) by this method ...

inside getIngredients() there is a call to Database.getDataReader(sql.ToSt.....

This works and I get a connection and a datareader:

[

 

Subscribe(Dynamicweb.Notifications.Standard.Page.OnOutput)]public class NotificationGlobalTags : NotificationSubscriber

{

 

{

Dynamicweb.Templatev2.

 

t.SetTag(

}

public override void OnNotify(string notification, object[] args)Template t = args[0] as Dynamicweb.Templatev2.Template;if (t == null) return;"Global:Recipes", getIngredients());
This don't and I get an sql timeout

[

 

Subscribe(Dynamicweb.Notifications.Standard.Page.OnGlobalTags)]public class GlobalTags : NotificationSubscriber

{

 

{

 

 

parameters.Template.SetTag(

}

public override void OnNotify(string notification, Dynamicweb.Extensibility.NotificationArgs args)var parameters = args as Dynamicweb.Notifications.Standard.Page.PageviewNotificationArgs;if (parameters == null) return;"Global:Recipes", getIngredients());
I don't see why?
 
Nicolai Høeg Pedersen
Reply
Do you get some kind of error?

getDatareader also works in that context...

 
Morten Bengtson
Reply
It sounds like you're forgetting to dispose the datareader used in getIngredients().

Do you access the datareader inside a using statement?

using(Database.getDataReader("SELECT * FROM Whatever"))
{
	while(reader.Read())
	{
		// do stuff with your data
	}
}
 
Kim Pedersen
Reply

Yes it works in that context, but the SQL server runs out of connections, just like it is called several times so that it eventually runs out off connections.
Like I wrote it is only a problem when calling it inside the Subscribe(Dynamicweb.Notifications.Standard.Page.OnGlobalTags)] it works fine when using it inside the [Subscribe(Dynamicweb.Notifications.Standard.Page.OnOutput)]

I don't think its a dispose problem but here is the code from inside the getIngredients():

..........
IDataReader DR = Database.getDataReader(sql.ToString(), "RecipeRecipeRelations.mdb");
try
                {
                    do
                    {
                        while (reader.Read())
                        {
                            Dynamicweb.Templatev2.Template objTemplate = new Dynamicweb.Templatev2.Template("../Templates/Recipes/Recipes.html");
                            objTemplate.SetTag("Amount", reader["Amount"].ToString());
                            objTemplate.SetTag("Unit", reader["Title"].ToString());
                            objTemplate.SetTag("Ingredient", reader["IngredientTitle"].ToString());
                            sb.Append(objTemplate.Output());
                        }
                    } while (reader.NextResult());
                }
                catch
                {
                }
                finally
                {
                    reader.Dispose();
                }
return sb.ToString();

 

 

 
Kim Pedersen
Reply

I found out that it is a bug in DW.

You can not use objTemplate.Output() inside the [Subscribe(Dynamicweb.Notifications.Standard.Page.OnGlobalTags)] because it will then call OnNotify again and again. In my case  it ran out off connections because I used it in a Loop like. The code below descripe my point.

 [Subscribe(Dynamicweb.Notifications.Standard.Page.OnGlobalTags)]
    public class GlobalTags : NotificationSubscriber
    {
        public override void OnNotify(string notification, Dynamicweb.Extensibility.NotificationArgs args)
        {
            var parameters = args as Dynamicweb.Notifications.Standard.Page.PageviewNotificationArgs;
            if (parameters == null) return;

            string productid = HttpContext.Current.Request.QueryString["productid"];
           
            if(!(parameters.Template.ContainsTag("Global:Recipes")))
            {
                if (!(string.IsNullOrEmpty(productid)))
                {
                    parameters.Template.SetTag("Global:Recipes", getIngredients(productid));
                }
            }
          
        }

public string getIngredients(string productid)
{
using(Database.getDataReader("SELECT * FROM Whatever")) {    
while(reader.Read())    
{        
sb.Append(objTemplate.Output()); // Now DW call OnNotify again and it starts all over again.
}
}
return sb.tostring();
}

 


 

 
Kim Pedersen
Reply
Any suggestions on how to do this in a differendt way if very welcome
 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

I don't think it's a bug, but by design.

The first time your code runs, you can add an item to the HttpContext.Current.Items collection. Then you can check for the presence of this item and when it's there, don't run the code again. E.g.:

if (HttpContext.Current.Items["Whatever"] == null)
{
  HttpContext.Current.Items.Add("Whatever", "someRandomValue");
  // Your code here...

Hope this helps,

Imar
 
Nicolai Høeg Pedersen
Reply
Not a real bug but a problem, I agree. Now with bug number 6645 which have been fixed and will be out with next service release.

Imars suggestion would help the problem.

Global tags are generated only once and then cached for all other template instances. But the Notifications.Standard.Page.OnGlobalTags notification is broadcast before the cache is set, causing and endless loop when the template object is used in this notification.

Now Notifications.Standard.Page.OnGlobalTags is only broadcast once on each http request.

 

You must be logged in to post in the forum