Comments & Ratings

Dynamicweb contains native support for posting and displaying comments and ratings (Figure 1.1) on both products and content pages.

Figure 1.1 An example of how comments & ratings may be used

Typically, this feature is implemented by creating a template and then using the @RenderPartial() or Include() methods to include it elsewhere.

The examples in this article use Razor templates with ViewModels as well as the API – but the feature can also be implemented using template tags and loops, if your solution is built on that technology.

Comments are posted by submitting a form with specific properties (Figure 2.1):

  • The id commentform
  • A set of relevant input fields with specific names and ids containing the comment data and other values controlling how the form behaves.
Figure 2.1 A comment form

From a user-perspective, a comment may contain the fields you see above – a name, an email, a website, and a rating.

From a frontender-perspective the full list of values you can pass to Dynamicweb using the form is shown below. Please note that there is no built-in validation – it is up to you to ensure that the user posts valid data.

Parameter

Required

Values

Comment

Comment.Command

Yes

create

 

Comment.Active

Yes

true/false

Set to false if you want to approve comments before publishing them.

Comment.ItemType

Yes

ecomProduct

page

Set to the item type being commented on – a product or content page

Comment.ItemID

Yes

A page or product id

 

Comment.LangID

Yes*

A ecommerce language ID

 

 

 

 

 

Comment.Continue

No

A URL

User is redirected to this URL after submitting the comment

Comment.ParentID

No

A comment ID

If this is a reply, you must find a way to set the value of this parameter to the ID of the comment being replied to.

 

This is typically done via javascript when the user clicks ‘reply’.

 

 

 

 

Comment.Name

No

A string

For user input

Comment.Email

No

A string

For user input

Comment.Website

No

A string

For user input

Comment.Rating

No

An integer

For user input

Comment.Text

No

A string

For user input

 

 

 

 

Comment.Notify

No

true/false

Set to ‘true’ send a notification to the email specified in Comment.NotifyEmail when a comment is posted.

Comment.NotifyTemplate

No

A path to an email template

-

Comment.NotifySubject

No

A string

-

Comment.NotifySenderEmail

No

An email

-

Comment.NotifySenderName

No

A string

-

Comment.NotifyEmail

No

An email

-

 

 

 

 

Comment.Reply.Notify

No

true/false

Set to ‘true’ to send a notification to the email registered on the parent comment when a reply is posted.

Comment.Reply.NotifyTemplate

No

A path to an email template

-

Comment.Reply.NotifySubject

No

A string

-

Comment.Reply.NotifySenderEmail

No

An email

-

Comment.Reply.NotifySenderName

No

A string

-

 

 

 

 

* Required only when commenting on a product

Comments can be rendered in frontend in a number of ways – for instance via the Comments loop in a product details template context, or by retrieving a comment collection via the API as demonstrated here:

RAZOR
Dynamicweb.Content.Commenting.CommentCollection comments = Dynamicweb.Content.Commenting.Comment.GetComments("ecomProduct", Model.Id, Model.LanguageId); @foreach (Dynamicweb.Content.Commenting.Comment comment in comments) { <div class="col-md-12 panel panel-default"> <div><b>Name:</b> @comment.Name</div> <div><b>Rating:</b> @comment.Rating</div> <div><b>Text:</b> @comment.Text</div> <div><b>Website:</b> @comment.Website</div> <!--The 'Reply' button calls the comment_reply function and changes the Comment.ParentID in the comment form to be the id of this comment--> <a class="btn btn-info btn-circle" onclick="comment_reply(@comment.ID)" id="reply"><span class="glyphicon glyphicon-share-alt"></span> Reply</a> </div> }

To render replies you can iterate trough the members of the comment.Replies comment collection:

RAZOR
Dynamicweb.Content.Commenting.CommentCollection comments = Dynamicweb.Content.Commenting.Comment.GetComments("ecomProduct", Model.Id, Model.LanguageId); @foreach (Dynamicweb.Content.Commenting.Comment comment in comments) { <div class="col-md-12 panel panel-default"> <div><b>Name:</b> @comment.Name</div> <div><b>Rating:</b> @comment.Rating</div> <div><b>Text:</b> @comment.Text</div> <div><b>Website:</b> @comment.Website</div> <!--The 'Reply' button calls the comment_reply function and changes the Comment.ParentID in the comment form to be the id of this comment--> <a class="btn btn-info btn-circle" onclick="comment_reply(@comment.ID)" id="reply"><span class="glyphicon glyphicon-share-alt"></span> Reply</a> </div> foreach (Dynamicweb.Content.Commenting.Comment reply in comment.Replies) { <div class="col-md-12 panel panel-default"> <div><b>Name:</b> @reply.Name</div> <div><b>ParentId:</b> @reply.ParentID</div> <div><b>Rating:</b> @reply.Rating</div> <div><b>Text:</b> @reply.Text</div> <div><b>Website:</b> @reply.Website</div> </div> } }

For a full list of comment and comment collection properties see the Dynamicweb.Content.Commenting namespace in the API docs.

If Comment.Active is set to false in the comment form – or if you need to remove offensive comments afterwards – you can review and moderate comments from the backend.

To do so log into the backend and navigate to either from Marketing > Comments or Ecommerce > Product Catalog > Comments where you will see a list of comments for this solution (Figure 4.1).

Figure 4.1 A comment list

To moderate a comment:

  • Click on it
  • Make changes
  • Click Save

You can also add new comments from the backend from either the product details view in the Ecommerce node or the Page properties > Advanced tab –  but be aware that if you retrieve e.g. the user object via an API call these comments will have no valid access user ID and that you will have to handle this in the template.

There are several ways to ensure that comment forms are not abused to post spam, e.g.:

  1. Put the form behind a login
  2. Setting Comment.Active to false in the form and approving comments manually
  3. Enabling Dynamicweb's built-in form antispam (requires DW 9.9+)

If you go for options three you need add a set of honeypot form fields to the comment form - these are fields only visible to bots, and which will result in a ban if filled in and submitted.

To render the fields:

  • In template-tag based designs they can be rendered via a template tag
  • In ViewModel based designs you must use the API to generate the markup as demonstrated below:
C%23
@{ var antispamfields = Dynamicweb.SystemTools.Security.FormAntispam.AntiSpamFields("commentform"); }

Then render the fields in the comment form in the regular manner:

RAZOR
<form method="post" action="/Default.aspx?ID=@pageView.ID" id="commentform"> <input type="hidden" name="Comment.Command" id="Comment.Command" value="create" /> <!--Antispam fields--> @antispamfields (...) <input class="btn btn-primary" type="submit" value="Post Comment" /> </form>

Below you will find a fairly simple example template implementing comments – this particular template is meant to be included in a ViewModel-based product details template using the RendePartial() method.

RAZOR
@RenderPartial("Ecom/ProductCatalog/CommentsSimple.cshtml")

A couple of notes about the example template:

  • The Comment.GetComments method is used to retrieve comments for a particular product & ecom language. Is using template tags you will have access to a Comments loop instead.
  • When replying to another comment, a simple javascript function is used to change the Comment.ParentID in the comment form to the ID of the comment being replied to

Without further ado:

RAZOR
@using System.Web; @using Dynamicweb.Rendering @using Dynamicweb.Ecommerce.ProductCatalog @inherits ViewModelTemplate<ProductViewModel> @{ Dynamicweb.Content.Commenting.CommentCollection comments = Dynamicweb.Content.Commenting.Comment.GetComments("ecomProduct", Model.Id, Model.LanguageId); var pageView = Dynamicweb.Frontend.PageView.Current(); var isLoggedIn = Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn(); var currentUser = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser(); } @*This function changes the Comment.ParentID value in the comment form to the id passed when clicking a 'reply' button*@ <script type="text/javascript"> function comment_reply(id) { document.getElementById("Comment.ParentID").value = id; } </script> <div class="row"> <div class="page-header"> <h3>Comments (@comments.TotalComments)</h3> </div> @foreach (Dynamicweb.Content.Commenting.Comment comment in comments) { <div class="col-md-12 panel panel-default"> <div><b>Active:</b> @comment.Active</div> <div><b>CommentID:</b> @comment.ID</div> <div><b>CreatedBy:</b> @comment.CreatedBy</div> <div><b>CreatedDate:</b> @comment.CreatedDate</div> <div><b>EditedBy:</b> @comment.EditedBy</div> <div><b>EditedDate:</b> @comment.EditedDate</div> <div><b>Email:</b> @comment.Email</div> <div><b>IP#:</b> @comment.Ip</div> <div><b>ItemId:</b> @comment.ItemID</div> <div><b>ItemType:</b> @comment.ItemType</div> <div><b>LangID:</b> @comment.LangID</div> <div><b>Likes:</b> @comment.Likes</div> <div><b>Name:</b> @comment.Name</div> <div><b>Rating:</b> @comment.Rating</div> <div><b>Text:</b> @comment.Text</div> <div><b>Website:</b> @comment.Website</div> <!--The 'Reply' button calls the comment_reply function and changes the Comment.ParentID in the comment form to be the id of this comment--> <a class="btn btn-info btn-circle" onclick="comment_reply(@comment.ID)" id="reply"><span class="glyphicon glyphicon-share-alt"></span> Reply</a> </div> foreach (Dynamicweb.Content.Commenting.Comment reply in comment.Replies) { <div class="col-md-12 panel panel-default" style="margin-left:30px"> <div><b>Active:</b> @reply.Active</div> <div><b>CommentID:</b> @reply.ID</div> <div><b>CreatedBy:</b> @reply.CreatedBy</div> <div><b>CreatedDate:</b> @reply.CreatedDate</div> <div><b>EditedBy:</b> @reply.EditedBy</div> <div><b>EditedDate:</b> @reply.EditedDate</div> <div><b>Email:</b> @reply.Email</div> <div><b>IP#:</b> @reply.Ip</div> <div><b>ItemId:</b> @reply.ItemID</div> <div><b>ItemType:</b> @reply.ItemType</div> <div><b>LangID:</b> @reply.LangID</div> <div><b>Likes:</b> @reply.Likes</div> <div><b>Name:</b> @reply.Name</div> <div><b>ParentId:</b> @reply.ParentID</div> <div><b>Rating:</b> @reply.Rating</div> <div><b>Text:</b> @reply.Text</div> <div><b>Website:</b> @reply.Website</div> </div> } } </div> <div class="row"> @if (isLoggedIn) { <form method="post" action="/Default.aspx?ID=@pageView.ID" id="commentform"> <input type="hidden" name="Comment.Command" id="Comment.Command" value="create" /> <!--Set to false if you want to approve comments before publishing them--> <input type="hidden" name="Comment.Active" value="true" /> <!-- Page comments --> @*<input type="hidden" name="Comment.ItemType" value="page" /> <input type="hidden" name="Comment.ItemID" value="@Model.Id" />*@ <!-- Product comments --> <input type="hidden" name="Comment.ItemType" value="ecomProduct" /> <input type="hidden" name="Comment.ItemID" value="@Model.Id" /> <input type="hidden" name="Comment.LangID" value="@Model.LanguageId" /> <!--Comment.Continue takes an URL to redirect the user to after submitting their comment --> <input type="hidden" name="Comment.Continue" value="@pageView.SearchFriendlyUrl" /> <!--Comment.ParentID should be set to the ID of the comment which is being replied to - here this is done via the comment_reply JS function--> <input type="hidden" name="Comment.ParentID" id="Comment.ParentID" value="0" /> <!--Notification email details--> <input type="hidden" name="Comment.Notify" value="true" /> <input type="hidden" name="Comment.NotifyTemplate" value="Comments/Notify.cshtml" /> <input type="hidden" name="Comment.NotifySubject" id="Comment.NotifySubject" value="New Comment on B&B: " /> <input type="hidden" name="Comment.NotifySenderEmail" value="noreply@dynamicweb.dk" /> <input type="hidden" name="Comment.NotifySenderName" value="Website comment" /> <input type="hidden" name="Comment.NotifyEmail" value="supplyyourownemail@email.com" /> <!--Notification email settings--> <input type="hidden" name="Comment.Reply.Notify" value="true" /> <input type="hidden" name="Comment.Reply.NotifyTemplate" value="Comments/ReplyNotify.cshtml" /> <input type="hidden" name="Comment.Reply.NotifySubject" value="" /> <input type="hidden" name="Comment.Reply.NotifySenderEmail" value="noreply@dynamicweb.dk" /> <input type="hidden" name="Comment.Reply.NotifySenderName" value="Webmaster" /> <!-- Comment Input Fields--> <div class="form-group"> <label for="Comment.Name">Name</label> <input type="text" class="form-control" name="Comment.Name" id="Comment.Name" value="@if (currentUser != null) {@currentUser.Name }" /> </div> <div class="form-group"> <label for="Comment.Email">E-mail </label> <input type="text" class="form-control" name="Comment.Email" id="Comment.Email" value="@if (currentUser != null) {@currentUser.Email }" /> </div> <div class="form-group"> <label for="Comment.Website">Website</label> <input type="text" class="form-control" name="Comment.Website" id="Comment.Website" value="" /> </div> <div class="form-group"> <label for="Comment.Rating">Your rating</label> <select class="form-control" name="Comment.Rating" id="Comment.Rating"> <option value="">Rate product....</option> <option value="1">1 (Poor)</option> <option value="2">2 (Below average)</option> <option value="3">3 (Average)</option> <option value="4">4 (Good)</option> <option value="5">5 (Great)</option> </select> </div> <div class="form-group"> <label for="Comment.Text">Comment </label> <textarea class="form-control" name="Comment.Text" id="Comment.Text" rows="10" cols="50"></textarea> </div> <input class="btn btn-primary" type="submit" value="Post Comment" /> </form> } else { <div class="col-md-12 panel panel-default"> <div class="text-center"><i></i></div> <div class="text-center"><a class="btn btn-primary" href="/Default.aspx?ID=59">Sign in</a></div> </div> } </div>
database

These are the database tables associated with Comments in Dynamicweb.

Comment

Contains comments for news, paragraphs, and items.

Field name Data type Length
CommentId int 4
CommentName nvarchar 255
CommentEmail nvarchar 255
CommentWebsite nvarchar 255
CommentRating int 4
CommentText nvarchar Max
CommentItemType nvarchar 25
CommentItemId nvarchar 35
CommentLangId nvarchar 25
CommentCreatedDate datetime 8
CommentEditedDate datetime 8
CommentCreatedBy int 4
CommentEditedBy int 4
CommentIp nvarchar 16
CommentLikes int 4
CommentNolikes int 4
CommentParentId int 4
CommentActive bit 1