Products

Solutions

Resources

Partners

Community

About

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

DotNetNuke 6.2 Developer Quick Start

Return to previous page

  • 4/7/2015
  • 12119 Views

Comments

12119 Views

DotNetNuke 6.2 Developer Quick Start

Last updated long time ago

Comments

Common

(Enter the content of this article below)

Advanced

 
Note: DotNetNuke 6.2 is at the community technology preview (CTP) stage - the information on this page is in a draft format as API's may change before the final release.

The DotNetNuke 6.2 Developer Quick Start page is intended to be used as a resource that can help get DotNetNuke extension developers up to speed on the latest offerings available in 6.2.0. If you are new to Skin Object, Module or Provider development in DotNetNuke, you may wish to visit the Module Development page for further details.

This wiki also contains similar pages for DotNetNuke 6 Developer Quick Start and DotNetNuke 6.1 Developer Quick Start which will be interest to those new to the 6.0 version(s).

Image




Services Framework

Services Framework allows developers to easily create a Web API that any "device" that speaks HTTP can call. In this sense "device" can be almost anything such as a smart phone, curl script, XmlHttpRequest. Almost anything that has an internet connection will do, and that means if you can write code for it, Services Framework will probably help you to integrate it with your DotNetNuke site. The single biggest convenience of Services Framework is that authentication, authorization and establishing a DotNetNuke context are all built in.

Service Framework is built on top of ASP.Net MVC 2. There are only a couple of small things that must be done a bit different in Services Framework than in ASP.Net MVC. In almost all cases when the question "How do I do X with Services Framework?" comes up, the answer is "The same way you do it in ASP.Net MVC.".

What's Different

Permission Defaults
By default in ASP.Net MVC everything can be called by eveyone with various attributes are then applied to tighten security. Services Framework takes the opposite approach, by default everything requires Host level access. Attributes are then applied to loosen those restrictions.

DnnController
All Services Framework controllers must inherit from DnnController. DnnController takes care of authentication and loading DotNetNuke context. Remember that by ASP.Net MVC convention controller names must end with "Controller" (e.g. MyFirstController).

DnnController also provides a few extra properties with some DotNetNuke context:

PortalSettings The settings of the current portal.

UserInfo The current user.

ActiveModule For services that are tied to a specific module (more on this below), will be null for services not tied to a specific module.

DnnAuthorizeAttribute
Very similar to the ASP.Net MVC AuthorizeAttribute, but with a couple extra properties and it works with DotNetNuke users.

StaticRoles The same as AuthorizeAttribute.Roles. That name was changed in anticipation of providing a more dynamic form of Role authorization that better fits the dyanmic nature of DotNetNuke roles.

RequiresHost Set this to true to require Host level access.

AllowAnonymous Set this to true to allow anonymous access.

IServiceRouteMapper
In ASP.Net MVC routes are normally mapped at Application_Start in Global.asax. In ServicesFramework routes get mapped after DotNetNuke is initialized, and after new portals are created. To allow proper mapping of routes, each Services Framework module must implement one instance of IServiceRouteMapper. Do not implement more than one instance of IServiceRouteMapper in a module. Doing so will cause the order of your routes to be undertermined.

When DotNetNuke needs to setup the routes, it will call RegisterRoutes on each ServiceRouteMapper implementation and pass it an object that implements IMapRoute.

IMapRoute
IMapRoute provides several overloads of the MapRoute method, which is used to actually map each route. The IMapRoute version of MapRoute is similar to the ASP.NET Mvc MapRoute with a few differences.

At minimum MapRoute requires:

string moduleFolderName This is typically the name of the folder in which the module is installed. This will be used as part of the route name that is required by ASP.Net MVC.

string url The url for your route. This exactly the same as the ASP.Net MVC parameter.

string[] namespaces An array of namespaces to search for controller to match this route. In ASP.Net MVC this is optional, in Services framework at least one namespace is required.

Optionally MapRoute supports:

object defaults This is exactly the same as the ASP.Net MVC parameter.

object constraints This is exactly the same as the ASP.Net MVC parameter.

Finally the return value also differs. ASP.Net MVC returns a Route object. Services Framework returns an IList. Depending on the portal configuration it may be necceary to create more than one route for each route specified. If required, the "real" name of each route can be found in
Route.DataTokens["Name"]
.

Security
Service developers should be aware of additional Services Framework Security considerations.

What's Added

TBD

Journal

The Journal is an activity stream of recent actions performed by an individual or group that is displayed on your DotNetNuke website. The Journal module displays a list of content presented in a variety of micro-formats that we refer to as Journal Types. In DotNetNuke 6.2 CTP1, we include four journal types which are: Status, Link, Photo and File. In DotNetNuke 6.2 CTP2, you will be able to create and manage additional Journal Types.

For information regarding the journal API, please visit the Journal page in the wiki.


Client Resource Management Enhancements

There have been a number of enhancements to client resource management in 6.2.0 - you can read about these in this blog


Changes to Tab Hierarchy Management

DotNetNuke 6.2.0 introduces changes to how the Tab (Page) Hierarchy is managed. Due to the limitations of earlier versions of SQL Server, prior to these changes, the business layer managed the handling of the tab hierarchy. Whenever a tab was created or moved in the hierarchy, there was a lot of calculation to calculate the effect on other tabs and update them accordingly.

In a large site like this one - if a tab with a large number of descendants is updated then every descendant is updated so that its "Level" and "TabPath" can be updated in the database.

SQL Server 2005 introduced the concept of "Common Table Expressions" or CTEs, which allow you to create recursive SQL scripts with fairly decent performance. Since we now require at least SQL Server 2005 as our base version of SQL Server, we have removed the Level and TabPath columns from the Tabs table and instead calculate them "on-the-fly" in the Tabs View.

This, in turn means that we don't have to do all the manipulation in the business layer in order to manage these properties.

In addition, we pushed more of the logic for creating and moving tabs into more explicit stored procedures e.g. MoveTabBefore, MoveTabAfter etc. A few methods in TabController that are no longer necessary have been deprecated and a few new ones created.

To give an example of the effect of these changes - consider a tab with 20 child tabs. To move one of those child tabs (in the Page Management module) to the top triggered 166 calls to the database in 6.1.2. In 6.2.0 this move triggers 5 calls to the database, and the guts of the work is done in a single stored procedure MoveTabBefore.

For the most part this change does not affect 3rd party developers unless they are manipulating pages, but the performance (and reliability) of moving tabs is now enhanced significantly.

Additional references


Changes to Maximum Roles

DotNetNuke 6.2.0 removes the maximum roles limitation of previous versions. Many developers are aware that, prior to version 6.2.0, a semi-colon delimited list of roles was saved in the user's cookie. As the cookie has a fixed size, this effectively limits the number of roles to which a user could belong to about 50.

Sometime during the 4.x/5.x time-frame we add a Roles property to the User and we began to cache users on the server side. It was therefore determined that the cookie caching of the user's roles was redundant, so this has been removed, which in turn removes the maximum roles limitation.

Additional references





Changes to Profile Visibility

DotNetNuke 6.2.0 CTP 1 introduces a number of Profile updates - many of which update the Visibility options..

Admin Only Properties - while this has always been available through the Visible property, this has been made clearer in the Help text for the property. A Profile Property whose Visible property is false cannot be viewed in the Profile page by the user (but is visible to Administrators when they edit the user's profile)

"Read Only Properties" - a Read-Only setting has been added to Profile Proeprties. ReadOnly Properties can be edited by Administrators (or through the API by Module Developers), but are Read-Only for the User him/herself.

Profile Visibility Enhancements - In order to support "Social" features like "Groups", "Friends" and "Followers" the Profile Visibility options have been extended, so that users can restrict visibility of individual Profile Properties to members of a particular Group or "Friends" or "Family". The UI for the Profile Visibility options has been enhanced to handle this.

Additional references


UserRelationship

Entities

RelationshipType

• The RelationshipType defines the core relationship types (Friend (2-way), Follower (1-way))

Relationship

• The Relationship class describes the relationships that a user or portal owns.

• A handful of default Portal-Level Relationships will be be present for every portal (e.g. Friends, Followers, Family).

• Portal-Level Relationship will have a -1 in UserID field.

• Any custom User-Level Relationship created by user will also be defined by this class (e.g. My InLaws, Engineering Group).

• User-Relationship will always have an associcated PortalID. User-Level Relationship will always be tied to a specific Portal.

UserRelationship

• The UserRelationship class defines the membership of the relationship.

• The user initiating the relationship is UserID.

• The target of the relationship is RelatedUserID.

• Status tracks relationship status as Initiated, Approved, Rejected etc.

UserRelationshipPreference

• The UserRelationshipPreference class defines the relationship preference per user

• The user initiating the relationship is UserID.

UserRelationshipStatus

The RelationshipStatus enum describes various UserRelationship statuses. E.g. Accepted, Blocked, Initiated.

None Relationship Request is not present (lack of any other status)

Initiated Relationship Request is Initiated. E.g. User 1 sent a friend request to User 2.

Accepted Relationship Request is Accepted. E.g. User 2 has accepted User 1's friend request.

Rejected Relationship Request is Rejected. E.g. User 2 has rejected User 1's friend request.

Ignored Relationship Request is Ignored. E.g. User 2 has ignored User 1's friend request.

Reported Relationship Request is Reported (for spam). E.g. User 2 has reported User 1's friend request for spam.

Blocked Relationship Request is Blocked. E.g. User 2 has blocked User 1's ability to send any request.


Relationship Business APIs

InitiateUserRelationship Initiate an UserRelationship Request

AcceptUserRelationship Accept an existing UserRelationship Request

RejectUserRelationship Reject an existing UserRelationship Request

ReportUserRelationship Report an existing UserRelationship Request.

IgnoreUserRelationship Ignore an existing UserRelationship Request.

BlockUserRelationship Block an existing UserRelationship Request

RemoveUserRelationship Remove an existing UserRelationship Request

Easy Wrapper APIs


AddFriend Initiating User initiates a Friend Request to the Target User

AddFollower Initiating User initiates a Follower Request to the Target User

GetFriends Get List of Friends (UserRelationship with status as Accepted) for an User

GetFollowers Get List of Followers (UserRelationship with status as Accepted) for an User

AddPortalRelationship Add a new Relationship for a Portal, e.g. Co-workers

AddUserList Add a new Relationship for an User, e.g. My Best Briends or My Inlaws.

Exceptions

• InvalidRelationshipTypeException

• UserRelationshipBlockedException

• UserRelationshipDoesNotExistException

• UserRelationshipExistsException

• UserRelationshipForDifferentPortalException

• UserRelationshipForSameUsersException

UserInfo.Social

• New Property Social of type UserSocial has been added to UserInfo class

• The UserSocial is a high-level class describing social details of a user.

• As an example, this class contains Friends, Followers, Follows lists.

• The UserSocial class lazy-loads the Lists.

New Portal Creation / Upgrade

• Default Friends and Followers Relationship is automatically created for any new Portal created.

• During Upgrade, all existing Portals get the above default Relationships as well

• By Default Followers Relationship is set to ‘Auto-Accept’ any Follower request. Friends request is not, the Target User will be required to Accept the relationship.

Global Inputfilter (Profanity Filter)

In DotNetNuke 6.2.0 API methods have been added to support filtering options for text (both replace and remove). One custom filter for profanity was added to the FilterFlag used by the InputFilter function - this will be used by the Journal function and can be reused by 3rd party module developers.

Details

First of all there are 2 new enumerations

public enum ConfigType

{
ListController,
ExternalFile
}

This supports the location of the filter terms - at present the only available option is ConfigType.ListContoller (ExternalFile has no implementation but will have one for the production release of 6.2.0)

public enum FilterScope

{
SystemList,
PortalList,
SystemAndPortalList
}

This supports the retrieval of the sets of filter terms - it allows for selection at the system (host) level, or the individual site (portal) level or combining both into one list.

In addition, the existing FilterFlag had NoProfanity added as an option to allow for that scenario to be easily called (and paired against other FilterFlags such as NoHtml/NoMarkup)

The class have 2 new methods (Remove and Replace) that can be called directly.

Profanity filter
To use the basic version of the profanity filter which sources it's filter terms from system and portal lists with the name "ProfanityFilter" a developer would do the following:

var ps = new PortalSecurity();

string somestring = objSecurity.InputFilter(txtString, PortalSecurity.FilterFlag.NoProfanity);

To pair this with existing filters a developer would call:

var ps = new PortalSecurity();


string somestring = objSecurity.InputFilter(txtString,
PortalSecurity.FilterFlag.NoProfanity |

PortalSecurity.FilterFlag.NoScripting |
PortalSecurity.FilterFlag.NoMarkup);

Replace/Remove functions
These instance methods can be invoked directly to do custom replace/removal of text. The existing ProfanityFilter can be replicated by calling the Remove/Replace methods and passing in the fixed name of the list (ProfanityFilter), setting it's config type to be a list and indicating that the list should be retrieved for both host and current portal

var ps = new PortalSecurity();

Remove(TempInput, ConfigType.ListController, "ProfanityFilter", FilterScope.SystemAndPortalList);

or

var ps = new PortalSecurity();

Replace(TempInput, ConfigType.ListController, "ProfanityFilter", FilterScope.SystemAndPortalList);

ConfigType has another option, but it is not currently implemented in the CTP. However the FilterScope is supported, so if a developer wanted to narrow the list they could do so as:

Only use host (system) list

var ps = new PortalSecurity();

Replace(TempInput, ConfigType.ListController, "ProfanityFilter", FilterScope. SystemList);

Only use portal (site) list

var ps = new PortalSecurity();

Replace(TempInput, ConfigType.ListController, "ProfanityFilter", FilterScope. PortalList);





SSL offloading

DotNetNuke supports SSL, and supports the ability to mark a page as secure. When "SSL-enforced" is enabled, pages can only load under a secure protocol request (HTTPS).

Some large enterprises have network devices (such as a load balancer) that support offloading SSL requests. In this configuration a network appliance such as a load balancer or proxy server receives the initial SSL (HTTPS) request and processes it before forwarding the request onto the webserver(s) as a HTTP request. As the request arrives at DotNetNuke for a HTTP page, DotNetNuke will detect that it should be loaded with the HTTPS protocol and redirect accordingly, causing a request loop to occur.

In 6.2.0, support was added to the professional and enterprise editions to allow DotNetNuke to check for the existence of a http server variable and if detected allow DotNetNuke to know that this is a request for a secure page delivered over a HTTP connection, allowing DotNetNuke to serve the page and not redirect to the HTTPS equivalent.

Secure user settings

In DotNetNuke 6.2.0 the DotNetNuke.Services.Personalization class was enhanced to support new methods which allow for the storing and retrieval of secure data. These values are automatically encrypted and decrypted when used.

Storing values

string setting = Convert.ToString(Personalization.GetSecureProfile("Usability", "UserMode" + PortalId));

or

string setting = Convert.ToString(Personalization.GetSecureProfile(objPersonalization,"Usability", "UserMode" + PortalId));

Retrieving values

Personalization.SetSecureProfile(dict["namingcontainer"], dict["key"], dict["value"]);

or

Personalization.SetSecureProfile(objPersonalization ,dict["namingcontainer"], dict["key"], dict["value"]);

Messaging

There is a very simple API available to SendMessage.

Namespace: DotNetNuke.Services.Social.Messaging

APIs

SendMessage

void SendMessage(Message message, IList roles, IList users, IList fileIDs);

void SendMessage(Message message, IList roles, IList users, IList fileIDs, UserInfo sender);

There are two overloads available to send message. The API has following parameters:

Message - Message object with To, Body, Subject, etc. filled-in
roles - List of roles you want to send message to. This parameter should only be passed if sender is Site Administrator or Group Owner
users - List of users you want to send message to.
fileIDs - List files you want to attach. The FileId is DNN FileId. This value can only be passed if Attachments are allowed (Admin->Site Setttings->Advanced->Messaging)
sender - UserInfo object of sender. This parameter defaults to currently logged-in user.

Notifications

Entities

NotificationType

The NotificationType class describes a single notification type that could be used to create new notifications. For example: FriendRequest, TranslationSubmitted, etc.

NotificationTypeAction

The NotificationTypeAction class describes a single action that can be associated to a notification type. For example: Accept, Reject, Delete, etc.

Notification

The Notification class describes the message received by a user as a consecuence of an action. It also includes custom information set by the creator of the Notification.

NotificationTypes Business Methods

CreateNotificationType. Creates a new NotificationType.

DeleteNotificationType. Deletes an existing NotificationType and its related data.

GetNotificationType. 2 overloads to get a single NotificationType by Id and Name.


NotificationTypeActions Business Methods

DeleteNotificationTypeAction. Deletes an existing NotificationTypeAction.

GetNotificationTypeAction. 2 overloads to get a single NotificationTypeAction. One by Id and the other by NotificationType and Name.

GetNotificationTypeActions. Gets a list of NotificationTypeActions belonging to a NotificationType.

SetNotificationTypeActions. Set the actions for a NotificationType.


Notifications Business Methods

SendNotification. Creates a new notification and sets its sender as the portal administrator.

CountNotifications. Returns the number of Notifications for a specified user.

GetNotifications. Returns a paginated list of Notifications for a specified user.

DeleteNotification. Deletes an existing Notification.

DeleteNotificationRecipient. 2 overloads to delete a recipient of a Notification by notification and user or by notification type, context and user.

DeleteAllNotificationRecipients. Deletes all NotificationRecipient for a specified notification.

GetNotification. Gets a single notification by id.

GetNotificationByContext. Gets a single notification by notification type and context.


How to create a new notification type

You can create a new notification type by using CreateNotificationType method in NotificationsController. Module developers could use this in conjunction with IUpgradeable interface. So during module installation, the required Notification types are created.

Some information has to be provided:

- A unique name.

- A description.

- A Time To Live (TTL) value that will be added to the notification creation date to calculate an expiration date, after which, the notification won't be displayed again. This value is optional.

- A DesktopModuleId. It will be explained later in the Localization conventions section. This value is optional.


How to create new notification type actions

After creating a new notification type, you can use the SetNotificationTypeActions method to create new notification type actions:

For each notification type action some information has to be provided:

- The notification type identifier.

- A resourcekey to get the name of the action. See Localization conventions section.

- A resourcekey to get the description of the action. See Localization conventions section.

- A resourcekey to get the confirmation message of the action. See Localization conventions section. This is optional and has to be used only when we want to display a confirmation before performing the action.

- The url of the service method that has to be called when performing the notification action. The url has to be a relative path without a starting '/', i.e. 'DesktopModules/YourModuleName/API/YourModuleService.ashx/ActionName'. See How to process notification actions section.


How to send a notification

In order to send a notification, you need to use the SendNotification method in NotificationsController. The information that you need to provide is:

- The notification type identifier. Tip: To get the identifier, you can use the GetNotificationType method using the NotificationType name.

- A subject.

- A notification body.

- The list of roles/users that will receive the notification.

- A boolean value indicating if we want to include a dismiss action.

- The sender identifier.

- Optionally, you can include extra information to be used while performing the action.

The most common scenario to create a new notification is:

var notificationType = NotificationsController.Instance.GetNotificationType("NotificationTypeName");

var subject = Localization.GetString("Subject", LocalResourceFile);
var body = Localization.GetString("Body", LocalResourceFile);
var sender = GetUser(); // Get the user that sends the notification.
var notification = new Notification
{
NotificationTypeID = notificationType.NotificationTypeId,
Subject = subject,
Body = body,
IncludeDismissAction = false,
SenderUserID = sender.UserID,
Context = "Any information you want to store here"
};

NotificationsController.Instance.SendNotification(
notification,
PortalSettings.PortalId,
new List<RoleInfo>(), // Pass here the list of roles or null if the notification is going to be sent to individual users only.
new List<UserInfo>(), // Pass here the list of users or null if the notification is going to be sent to roles only.
); // There is an overload that doesn't receive this parameter and uses Admin as sender.


How to process notification actions

Notification Actions are performed by Service Framework methods. See Service Framework blog post to know how to create them.


By convention, these methods are going to receive one single parameter: int notificationId.

Another convention is that the method has to return a Json object with a string property named Result. This property could have two values: "success" or "error". If there is an error, you can include an optional string property named Message with the description of the error.

Usually, after the action has been performed, you will want to remove the notification from the UI. In order to do this, you could call the DeleteNotificationRecipient method.

One important thing to notice is that in order to avoid security problems, you have to check if the current user is a recipient of the notification. That is done in the first 2 lines of the example below:

[DnnAuthorize]

public ActionResult AcceptFriend(int notificationId)
{
try
{
var recipient = MessagingController.Instance.GetMessageRecipient(notificationId, UserInfo.UserID);
if (recipient != null)
{
var action = NotificationsController.Instance.GetNotificationAction(notificationId, "Accept");
var key = action.Key;
int initiatingUserId;
if (int.TryParse(key, out initiatingUserId))
{
RelationshipController.Instance.AcceptUserRelationship(GetFriendUserRelationship(initiatingUserId).UserRelationshipId);
NotificationsController.Instance.DeleteNotificationRecipient(notificationId, UserInfo.UserID);
return Json(new { Result = "success" });
}
}
return Json(new { Result = "error" });
}
catch (Exception)
{
return Json(new { Result = "error" });
}
}

Localization conventions

NotificationTypeAction class contains three properties named NameResourceKey, DescriptionResourceKey and ConfirmResourceKey that contain the keys to localize the name, description and confirmation message for each action.

The question is, where to store that translations? Well, there are two options here, but the most common scenario would be to create a file named SharedResources.resx into the App_LocalResources folder of your module and provide your modules' DesktopModuleId while creating the NotificationType.

If you don't provide a DesktopModuleId, the SharedResources.resx file in App_GlobalResources folder located in the root folder of your DotNetNuke installation will be used.

If none of these files are found, the value stored in that property would be used.

Integrated Modules

These are modules (not distributed with the core) that are integrated with new 6.2 features (relationships, journal, notifications, services framework, etc.) and therefore require a dependency of DotNetNuke 6.2 or greater.

List at Launch:
  • Active Forums 5.0
  • DotNetNuke Blog 5.0
  • DotNetNuke Contest 1.x
  • DotNetNuke Q&A 1.x

Contents
No sections defined
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out