My name is Steve Roth and I’ve been developing web software longer than I care to admit. DNNSoftware’s Evoq platform has been my platform of choice for many projects. And for each of those projects, DNN Sharp tools has been integral to the project’s success.
I’ve used all DNN Sharp tools, but for this series of blog posts I’m going to focus on 4 specific tools. My Tokens, Action Form, Action Grid and DNN API Endpoint. Why these four? Because these tools are arguably the most powerful 3rd party applications available for rapidly building low cost, highly functional web applications.
I’m not being paid or writing to endorse DNNSharp. My sole objective with these blog posts is to give back to the community at large, and to share use cases that may prove useful to others developing web applications using Evoq and DNNSharp tools.
My posts will not be highly technical, but do assume you have working knowledge of DNN Evoq, DNNSharp tools and SQL. All of my use cases will be using a SQL database and tables that you can easily replicate in your own environment.
This blog post will focus on My Tokens. If I were forced to choose one development application for use with DNN Evoq, it would be My Tokens. It’s powerful, fast, bulletproof, and core to most all other DNNSharp applications. I’m continually amazed at the number of use cases there are for tokens and how easy they are to incorporate into applications. The core set of tokens available are self-explanatory. Well, most are. Others require a little more explanation. Custom tokens, however, is where the real power of My Tokens is realized.
A My Tokens module instance should be installed for each portal that you have. When you create tokens they can be made available on ALL portals or just available on the portal instance where it’s installed. This is a powerful feature giving you the ability to create a token that is available across all of your sites.
My Tokens has a few setup options worth noting. One is Cache Time and the other is Layer setting. Cache Time isn’t required, but is used to speed things up especially if the token source is anything but a constant; for example, a database query. The cache time is in seconds. If I set the cache to 86400 and use the token for a database query, then the token will only execute the database query every 24 hours regardless of how many times it’s referenced. The Layer setting is also very powerful. The “Global” setting means that a single cache timer will be across all portals, users, roles, etc. The “Portal” setting means that each portal you have can reference the same token, but each portal will have a unique cache timer. “Per User” means that that the Token will maintain an independent cache timer for each user. Using the same database token example: If User A logs into a portal for the first time and the Token is referenced in some manner, the database query will execute and User A’s cache timer is set to 24 hours. If User B logs in an hour later and references the Token, the database call is made and their cache timer is set for 24 hours. User A’s cache timer is still ticking down with 23 more hours to go before it will make the database call again. The “User Session” has the same attributes as the “Per User” setting, except that the cache timer will reset for each new session regardless of how much time is remaining on that User’s cache timer. The “Per Role” setting maintains a cache timer for a specific role, instead of a user.
So let’s set up an example of how Cache Time, Layer Setting and another powerful capability called Token Parameters are used.
I have two sales people and a sales manager that access a portal. I have a SQL table called Orders with four columns OrderID, UserID, OrderDate and OrderValue. OrderID is a unique identifier and primary key for this table. I'll be using this example on future blog posts, so follow steps 1 and 2 to create this on your test environment.
|STEP 1 – Create the Table
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[Orders](
[OrderID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NULL,
[OrderDate] [datetime] NULL,
[OrderValue] [money] NULL,
PRIMARY KEY CLUSTERED
([OrderID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
STEP 2 – Insert 4 rows of data
INSERT INTO dbo.Orders
(1, GETDATE(), 1000.00),
(1, GETDATE(), 5000.00),
(2, GETDATE(), 10000.00),
(2, GETDATE(), 4000.00);
A query of this table returns the following:
Now I’m going to create a Token to get access to this data. First I’m going to create a Namespace called Sales. A namespace is simply a group of tokens. Notice that I have not created this Namespace to be used across all portals. This Namespace is strictly for use on the current portal and will not be visible on other My Tokens instances that you may have on other portals.
Next I’m going to create a custom token called OrdersTotals and want this token to return two values: Total Number of Orders and Total Value of all Orders. The Layer is Per Portal and Cache Time is 3600 seconds or one hour. This means that this token will only be refreshed every hour.
Two Tokens have been created (One for each column Name in the query). Notice that in my SQL query I’ve used SUM and COUNT, and another powerful capability of My Tokens called the Token Parameter. This means that when the token is used, a value for UserID will be passed into the token as a parameter and used in SQL query.
A simple usage for this token would be to explicitly pass in a UserID:
[Sales:OrderTotals.TotalOrders(UserID=1)] and [Sales:OrderTotals.TotalOrderValue(UserID=1)]
To test the tokens I’ve placed them into a DNN HTML module. Note: Make sure that Replace Tokens is checked in the HTML module settings.
So now for a little of the magic! Change the Token layer User Session and instead of explicitly passing in the value of 1 as a token parameter, use one of the core Tokens. I’m going to use the User token for this example:
[Sales:OrderTotals.TotalOrders(UserID=[User:UserId])] and [Sales:OrderTotals.TotalOrderValue(UserID=[User:UserId])]
This will pass the UserId of the current User as the token parameter and if there are any records that match that user in the Orders database table, it will display the results. The token will be executed at login for every unique User's session, but because the cache time is set to 3600 the token will only refresh once every hour during that session. If you'd rather have the token refresh every time it's referenced (query the database) during the session, simply set the cache time to zero. Just understand the performance implications of repeated queries for your application.
I hope this was helpful and I look forward to expanding on this example in future posts.