About this article

Written by:
Posted:
07/07/2010 15:14:47

About the author

Imar Spaanjaars is the owner of De Vier Koeden, a company specializing in consultancy and development on the Microsoft .NET platform and DynamicWeb.

Interested in custom development or consultancy on DynamicWeb or .NET? Then contact De Vier Koeden through the Contact page.

If you want to find out more about Imar Spaanjaars, check out his About page on this web site or check out his personal website.

NotificationSubscribers - Part 3 - Extranet Logins

This is part 3 in a series on Dynamicweb NotificationSubscribers that enable you to hook into some of the interesting events that occur in the life cycle of a Dynamicweb page. If you're new to NotificationSubscribers, be sure to check out part 1 of this series which gives you a thorough introduction to them.

In this part: hooking into OnExtranetLoginFailed.

Introduction

For some reason, Dynamicweb doesn't provide you with a lot of feedback about failed attempts to login to the Extranet module. Unlike what you would expect, there is no ExtranetLoginFailedtemplate or a similar template tag that would enable you to set a custom message when the login failed.

Fortunately, it's easy to implement this yourself using a NotificationSubscriber. If your login box is placed inside a Page template, that is all you need. Otherwise, you may also need some client code (such as jQuery) to display the error message in the correct location of the page. I'll show you the Page based version first, followed by the paragraph version.

Showing the Login Failed message

To show a "Login failed" message using a NotificationSubscriber you need to execute the following steps:

  1. Create a NotificationSubcriber class that listens to the Standard.User.OnExtranetLoginFailed notification.

  2. In the OnNotify method, add a template tag to the current page's template. To make this solution generic and localizable, you shoudn't set the actual error message from the NotificationSubscriber, but instead just add a template tag to indicate some error occurred (an incorrect user name or password was entered, the account is expired etc).

  3. Inside your page template, add some code that checks if the login failed template tag has been set, and then shows an error message to the user.

In the following section, you see how to accomplish this.

1. Create a NotificationSubcriber

Add a new class called ExtranetLoginSubscriber to your Custom Modules project or to your custom Class Library project used by your web application. Refer to part 1 in this series for more instrutions on setting up your project for NotificationSubscriber classes.

Modify the class so it ends up as follows:

using System;
using Dynamicweb.Extensibility;
using Dynamicweb.Frontend;
using Dynamicweb.Notifications;
namespace Dynamicweb.Samples.Lib
{
  [Subscribe(Standard.User.OnExtranetLoginFailed)]
  public class ExtranetLoginSubscriber : NotificationSubscriber
  {
    public override void OnNotify(string notification, NotificationArgs args)
    {
    }
  }
}

Notice how you need to override the OnNotify method that accepts a Notification instance. The other overload, that accepts an object[] is not triggered for a failed login.

2. Add template tags in the OnNotifty method

Inside the OnNotify method you need to write code that sets template tags you can respond to in the page template. Modify the code as follows:

public override void OnNotify(string notification, NotificationArgs args)
{
  Standard.User.OnExtranetLoginFailedArgs loginArgs = 
                     args as Standard.User.OnExtranetLoginFailedArgs;
  string tagKey = String.Format("ExtranetErrorMessage{0}", loginArgs.Reason);
  PageView myPageView = PageView.Current();
  myPageView.TemplatePage.SetTemplateValue(tagKey, "true");
  myPageView.TemplatePage.SetTemplateValue("ExtranetErrorMessageExists", "true");
}

The args argument of the OnNotify method is of type OnExtranetLoginFailedArgs. This type has a property called Reason which is an enum of type Dynamicweb.Notifications.Standard.User.OnExtranetLoginFailedArgs.FailReason that has three members: IncorrectLogin, PasswordExpired, and PasswordLengthInvalid. Depending on the reason for the failed logon attempt, the Reason property has one of these three values. Instead of acting on this reason directly, the code creates a tag key with the static text ExtranetErrorMessage combined with the reason. So, if your user name or password are incorrect, the tag name ends up as ExtranetErrorMessageIncorrectLogin. Additionally, the code sets a tag called ExtranetErrorMessageExists that tells you an error occurred, regardless of the actual reason for the error. Using this tag makes it easier in the template to add some code regardless of the actual login error.

3. Write code in your template to respond to the failed log in attempt

The final step is to add code to your template that displays a message to the user if an error occured. The code can use the generic ExtranetErrorMessageExists template tag to output some HTML that applies to all errors (e.g. to add a span with an error-message class for example) and then uses If Defined on the three different "reason" template tags to display an appropriate message. The template could look like this:

<!--@If Defined(ExtranetErrorMessageExists)--> 
  <span class="error-message">
  <!--@If Defined(ExtranetErrorMessageIncorrectLogin)--> 
    Incorrect password or user name; please try again.
  <!--@EndIf(ExtranetErrorMessageIncorrectLogin)-->
  <!--@If Defined(ExtranetErrorMessagePasswordExpired)--> 
    Login failed, your password has expired.
  <!--@EndIf(ExtranetErrorMessagePasswordExpired)-->
  <!--@If Defined(ExtranetErrorMessagePasswordLengthInvalid)--> 
    Your password is not valid.
  <!--@EndIf(ExtranetErrorMessagePasswordLengthInvalid)-->
  </span>
<!--@EndIf(ExtranetErrorMessageExists)--> 

When you view the page with the ExtranetLoginSubscriber and this code in a page template in your browser and enter an incorrect user name and password, you'll see the appropriate error message appear.

Dealing with error messages in Paragraphs

Unfortunately, to my knowledge, you cannot access a paragraph template from within a NotificationSubscriber. That means you can't assign the error message to a paragraph template directly. However, with a bit of jQuery this isn't too hard to accomplish.

First, make sure that a reference to the jQuery library is included in your page somewhere. Next, wrap the <span> with its class set to error-message in a pair of <div> tags. Assign the <div> an id and a style attribute that hides it by default. You should end up with something like this:

<!--@If Defined(ExtranetErrorMessageExists)-->
<div id="errorMessageWrapper" style="display: none;">
  <span class="error-message"> 
... </span> </div>

Below the <div> element, write some  jQuery code that grabs the inner HTML from the <div> element and assigns it to some other element in the page:

<script type="text/javascript">
$(function ()
{
$('#errorMessageTarget').html($('#errorMessageWrapper').html());
});
</script>

The final step is to create a <div> (or any other element) on your page that serves as the target for the error message. In my case, I added the following <div> element to a paragraph template that I use to display content in the footer area of the page where I display status messages:

<div id="errorMessageTarget"></div>

And that's it. When you now try to log in with an incorrect user name or password, the NotificationSubscriber fires which creates the ExtranetErrorMessage template tag. This adds some HTML to your page with the error message and a bit of jQuery code that gets executed as soon as the page has finished loading. This jQuery code then takes the HTML from the original <div> element and assigns it to some other element you defined elsewhere in the page structure.

This gives you a pretty flexible solution. Without requiring a lot of code, you can respond to various Login Failed events and display code anywhere in your page.

Downloads

Download the source for the NotificationSubscriber and templates

By clicking 'Accept All' you consent that we may collect information about you for various purposes, including: Statistics and Marketing