Warn user about unsaved changes before leaving the page

Warn Users in AdvanceAn Editing Session Handler for Navigating Away Alerts

Hey we all have gone thru the job of making sure a user doesn’t have pending modifications to be saved before navigating away from our page. If you haven’t, then I sure hope this helps you out.

The way I see this, there are 2 main scenarios in which we will want to do this:

  1. User has a form with updated data, and after changing the value of some <input> or <select>, the user tries to close the tab or window, or hits “Back” button on the browser
  2. The user has a form with updated data, but this form is really a “sub form” which is entirely AJAX submitted. Here, we want to warn the user that the subform has pending changes before he/she posts the form, closes the tab or window, or hits the “Back” button on the browser.

We’ll address the second scenario. Imagine an scenario where you want to edit a User profile, and part of the profile is an AJAX-editable list of preferences. The following is a Razor View file.

@model MvcApplication1.Models.Home.HomeViewModel

<h2>
    Index</h2>
@using (Html.BeginForm())
{
    <div>@Html.LabelFor(m => m.Username):</div>
    <div>@Html.TextBoxFor(m => m.Username)</div>
    
    <div>@Html.LabelFor(m => m.FullName):</div>
    <div>@Html.TextBoxFor(m => m.FullName)</div>
    
    int idx = 0;
    <h3>
        Favorite Numbers</h3>
    foreach (var favNumber in Model.FavoriteNumbers)
    {
        <div style="display: block;">@Html.Hidden("index", idx++)
            @favNumber
            <a href="#">Edit</a>
        </div>
    }
    
    <input type="submit" value="Submit" />
}

I’m not gonna post here a fully functional example cause that’s really not my intention (plus don’t have the time :)). So imagine that that Anchor tag you see there right next to the Favorite Number (favNumber) would:

  • Turn the “number” on the DOM into an <input type=”text” /> for editing.
  • Turn the Anchor itself into 2 Anchors (Save and Cancel).

That is all using Javascript (jQuery or whatever) of course. So now, what you want to do is handle the click on those “Save” links to do an AJAX post to the server to update the favorite number.

$("a.save").click(function () {

    $.post({ fav: $(this).parent().find("input").val() });
});

But what if the user:

  1. Loads the page for the User Profile
  2. Clicks on Edit to edit the first Favorite Number
  3. Updates the favorite number to “23”
  4. Clicks on “Submit”

That Submit will actually post the form with the Username and Fullname, but will NOT include the edited favorite number (actually it will, but not thru the AJAX feature you’ve envisioned).

So, an elegant way to handle this is to have a warning box appear to the user anytime the user tries to Submit a form (or navigate away from the page) with unsaved changes. I thought it would be useful to have a “stack” like feature that would allow the user to initiate as many edits as he/she wants, and warn when navigating away for as long as there is at least 1 pending edit to be commited (either saved or canceled).

So… here it is:

/*

* This global object will allow control over current pending modifications to be commited, and will
* warn the user whenever he/she tries to leave the page without committing them.
*
* Author: Mauricio Morales <mmorales@prosoftnearshore.com>
* This code is provided as-is, and we (Prosoft Nearshore) provide no support or warranty.
*/
UnsavedChangesWarning = new function () {
    /// Stores the current pending number of commits
    this.pendingCommits = 0;
    /// Stores a map of all callbacks
    this.callbacks = new Object();
    /// Pushes a new unsaved modification to be warned about. You should call this function when you
    /// start a modification that you want to warn the user about.
    /// The ID will uniquely identify your callback.
    this.push = function (id, callback) {
        this.pendingCommits++;
        if (id && callback) this.callbacks[id] = callback;
        // If this is the first change, then
        if (this.pendingCommits == 1) {
            window.onbeforeunload = function () {
                for (var key in UnsavedChangesWarning.callbacks) {
                    UnsavedChangesWarning.callbacks[key]();
                }
                return 'You have unsaved changes and will be lost! Are you sure you want to leave this page?';
            }
        }
    };
    /// Pops an old unsaved modification to be warned about.
    /// You should call this function when the user has either saved or canceled a modification.
    this.pop = function (id) {
        this.pendingCommits--;
        // if an ID is provided, then remove the callback
        if (id) delete this.callbacks[id];
        // if no more pending commits, then release the unsaved changes warning
        if (this.pendingCommits <= 0) {
            window.onbeforeunload = null;
        }
    };
};

What you’ll do is, simply, call that UnsavedChangesWarning.push(…) function when you start an AJAX editing mode/session. Then, call the UnsavedChangesWarning.pop(…) when the editing session is commited. This way, for as long as there is a push without a corresponding pop, the browser will alert the user when navigating away.

You can call that .push(…) function in 1 of 2 ways:

// this way, it'll just keep the push as a counter

UnsavedChangesWarning.push();
// this way, you can specify a callback to modify your DOM to somehow alert the
// user that the pending changes are <here>
UnsavedChangesWarning.push("mychanges", function () {
    $("input").css("color", "red").focus();
});

Now… correspondingly, the .pop() has 2 ways:

// this corresponds to the .push() call

UnsavedChangesWarning.pop();
// this corresponds to the .push(id, callback) call
UnsavedChangesWarning.pop("mychanges");

I won’t be held responsible for anything weird that may happen if you call a .push(id, callback) with a .pop(), or viceversa :).

What’s Good

  1. You can have several “editing sessions” all over your page, and the feature will handle them all nicely. And it even provides means of notifying the user of where are those open sessions.

What’s Bad

  1. It isn’t really that bad, but it won’t handle the first scenario for when we want the navigating-away warning (that’s, when the user modified some form <input>s and tried to hit back or close the browser.

What Could be Better

  1. It could somehow account and cover for that first scenario as mentioned above (in the What’s Bad first bullet).
  2. The name “UnsavedChangesWarning” isn’t really the best name for it, but I figured the feature was more important for the time being :).

Drop us a comment if you found this useful, or if you got feedback.

Acceptance Test-Driven Development

Acceptance Test DrivenIn our constant effort to continually improve our software processes, we’re beginning to explore Acceptance Test-Driven Development!    This would fit in with the current Agile model we employ and would help make sure we have more buy-in from the Product Owner in the planning process and make it easier for him/her at the same time.

Acceptance Test-Driven Development is a way to write the acceptance tests in advance and have the end user agree on the exact functionality before writing the code. Then the code can be written (and tested) without the need for extensive UAT (and bug fixes) after the fact.  Find out more about ATDD here.

There are many tools available such as Robot FrameworkCucumber (Ruby), FitNesse and Concordion.  We have begun to use FitNesse on a trial basis.  FitNesse is an integration testing tool that allows you to easily create and run automated tests and then verify that the code passes (or fails).  The important thing to note is that these tests apply to the business logic only – they do not test validations on text boxes and things like that.  But, you’ll know that your functionality is all there before you turn it over to UAT.  For more information about FitNesse go to www.fitnesse.org.

We would love to hear from you if you have worked with Fitnesse or any of the other tools out there and what your experience has been.

Simple Mail Service

Keep it SimpleOver the past years, I’ve found myself having to write down a mailing component for the projects that I’ve been involved… but none like this one that I decided to post.

First of all, I want to set the disclaimer that I do not think this is a revolutionary design or even unique in any sort… it is just the product of me designing a new application right after I finished reading this book. Amongst many things I read in this book, which by the way, I think it’s a MUST read for every ASP.NET MVC developer, was the concept (in practice) of Dependency Injection.

Up until now, I had thought of Dependency Injection as a simple matter of filling dependencies of other objects (and indeed, that’s what it is!!) but never really realized the power of it until I saw a DI Factory working on Steven Sanderson‘s book samples… and I trust you’ll too catch a glimpse of it through this example.

The Mail Service

Let’s get to the good stuff now (after that boring intro ). The first thing to start with, and isn’t really a breakthrough is the fact of thinking of the Mail Service as a “Service” (duhh!), instead of a helper class or extension methods or whatever other ideas you may have had or found. It’s a business (more application really) layer in it’s whole… and we should treat it with the isolation it deserves.

But wait!!, before we go any further, let me break your mind if you are already thinking that because you are building a service, then the service will know how to construct and send EACH and EVERY single Email that your application needs to send… WRONG!! I’ve gone that path before, and believe me… it’s no sunshine when it comes to maintain it.

So, what we are really building here, is a simple Email SMTP Sender service. Let’s start off by a simple interface:

public interface IMailService
{
    void Send(IMailTemplate template);
}

Simple enough, it’s all we really need for a Simple Mail Service. Feel free to extend and share if you find it useful and make further improvements. But if you noticed, and this is the beauty of the simplicity Dependency Injection provides… this mail sender doesn’t know anything (or very few) about the emails it is sending… it is, again, a SENDER… not a builder.

The Mail Template

Who really handles the content being delivered is (in concept) this IMailTemplate interface:

public interface IMailTemplate
{
    string From { get; }
    IEnumerable<string> To { get; }
    IEnumerable<string> Cc { get; }
    IEnumerable<string> Bcc { get; }

    string Subject { get; } 
    string Content { get; }
    bool IsContentHTML { get; }

    IEnumerable<Attachment> Attachments { get; }
}

This Mail Template is nothing but a builder of a single purpose message. It’s an interface! so you can implement it as many times as you like, with as many different purposes, formats, attachments and even embedded images in HTML as you like.

Concrete Implementations

To show you what the concrete (and probably most common) implementation of IMailService would be, here’s my simple SmtpMailService:

public class SmtpMailService : IMailService
{
    #region IMailService Members

    public void Send(IMailTemplate template)
    {
        try
        {
            SmtpClient client = new SmtpClient();

            MailMessage mailMessage = new MailMessage();

            foreach (var toMail in template.To)
            {
                mailMessage.To.Add(toMail);
            }

            foreach (var ccMail in template.Cc)
            {
                mailMessage.CC.Add(ccMail);
            }

            foreach (var bccMail in template.Bcc)
            {
                mailMessage.Bcc.Add(bccMail);
            }

            mailMessage.Subject = template.Subject;
            mailMessage.Body = template.Content;
            mailMessage.IsBodyHtml = template.IsContentHTML;

            foreach (var attachment in template.Attachments)
            {
                mailMessage.Attachments.Add(attachment);
            }

            client.Send(mailMessage);
        }
        catch { throw; }
    }

    #endregion
}

While leaving plenty of room for improvement, it pulls the job. So all we have to do now, is create our own implementation of the IMailTemplate interface, and we should be ready to start spamming .

I got the following template from a personal project I’m working on… so forgive me if it doesn’t compile out of the box:

public class SuccessfulRegistrationMailTemplate : name.space.IMailTemplate
{
    private User _User;
    private Person _Person;

    public SuccessfulRegistrationMailTemplate(User registeredUser, Person person)
    {
        this._User = registeredUser;
        this._Person = person;
    }

    #region IMailTemplate Members

    public string From { get { return null; } }

    public IEnumerable<string> To
    {
        get { return new string[] { this._User.Email }; }
    }

    public IEnumerable<string> Cc
    {
        get { return new string[0]; }
    }

    public IEnumerable<string> Bcc
    {
        get { return new string[0]; }
    }

    public string Subject
    {
        get { return "Successful Registration - MyWebSite.com"; }
    }

    public string Content
    {
        get
        {
            StringBuilder content = new StringBuilder();
            content.Append("<html><body>");
            content.AppendFormat("<h1>Welcome {0}</h1>", this._Person.FirstName + " " + this._Person.LastName1 + (this._Person.LastName2 ?? ""));
            content.AppendFormat("<p>Welcome to MyWebSite.com.</p>");

            HttpContextWrapper contextWrapper = new HttpContextWrapper(HttpContext.Current);
            UrlHelper helper = new UrlHelper(new RequestContext(contextWrapper, RouteTable.Routes.GetRouteData(contextWrapper)));
            content.AppendFormat("<p>Your Account {0} has been created successfully. Click <a href='{1}'>here</a> to start your session.</p>", this._User.Email, helper.Action("Index", new { controller = "Home" }));
            content.Append("</body></html>");

            return content.ToString();
        }
    }

    public bool IsContentHTML
    {
        get { return true; }
    }

    public IEnumerable<System.Net.Mail.Attachment> Attachments
    {
        get { return new System.Net.Mail.Attachment[0]; }
    }

    #endregion
}

So you can easily send this email like this:

this.MailService.Send(new SuccessfulRegistrationMailTemplate(newUser, newPerson));

And that’s it!

Where is the Dependency Injection part?

In case you missed it, the Dependency Injection comes when the sender receives the IMailTemplate, and asks it for the actual content to construct the MailMessage object with. This is basically “Injecting” the mail addresses, content and attachments into the IMailService sending logic. You can even put DB queries in there! or other Web Service or REST calls!

The Benefits

I’ve tried before constructing these huge moster service or components that would basically know how to build and mail each and every single mail that the system needs to mail out… and end up with an engine, so generic and flexible, that is almost imposible to understand the outcome when you look at the business layer that wants to send the email. So in this approach, I’ve managed to simplify the sending layer, and leave the specifics of each different message to it’s own implementation class.

Another benefit from this is the fact that this is refactorable and redistributable in different projects, as the format and content details are all outside the MailService itself. When I refactor it myself, I’ll make sure I publish it here so everyone can download it’s source and binaries.

Improvements (TODO list)

Well, here’s the list of things that I know you can and may want to put in there… but I just haven’t justified the time to do it.

  • HTML Templating: This kind of beats the “simple is better” approach cause introducing HTML templating with String token replacements will most likely turn this simple Mail Service into an obscure unmaintaineable monster… but hey, who am I to judge? I do grant the fact that in very simple and small applications, it’s probably easier to have HTML token replacements than dynamic HTML construction. Perhaps you are considering this for a CMS… you never know…
  • Asynchronous Programming Model (APM): There’s a single “Send” method on the Mail Service, but it’d be great if it had a BeginSend and EndSend for asynchronous mail sending. It’s all possible!
  • Queuing and Retrying: Though this is way beyond the features of a Simple Mail Service, handling mail sending using a Queue and Retrying whenever the error can be picked up during an SMTP send can turn very beneficial to largely loaded applications.
  • Non-SMTP delivery: You may verywell want to deliver messages not using SMTP. Perhaps a pickup folder of the local SMTP service, or an XML messaging model for console-geeks… whatever it is, this model actually applies to any construction of messages… not just Email messages.
  • View Engine Templates: I left this to the last, but highlighted it cause it’s far from being the least important. You can setup an IMailTemplate implementation that uses the View Engine of an ASP.NET MVC application (if you are building an MVC web site, of course :)) to generate your mail contents using the Controller-View architecture. This is similar to what MvcMailer and ActionMailer do.

Hope you enjoyed this post, and please leave your feedback on your way out!

 

 

 

 

 

 

 

 

 

 

Message from the President

A Message From the PresidentFour years ago, I knew as much about Costa Rica as I did about Aruba or Puerto Rico or a number of other vacation destinations.  I knew it as a tropical paradise that was on my list to visit, but that was about it.  It wasn’t until one of my clients began assembling a development team in Costa Rica that I came to know about the talented software developers there.  I opened our office in Costa Rica in the Fall of ’08 as an alternative to Indian off-shore, especially for clients that wanted to have distributed Scrum teams.  I ascribe to Jeff Sutherland’s line of thinking; distributed scrum teams are far more productive than separate teams and give you all of the advantage of off-site workers, while rivaling the velocity of a local team.  By having off-site team members in Latin America, our clients are able to better leverage their SME (Subject Matter Expert)s by having them work directly with the off-site developers without having to deal with all of the communication overhead and additional detail in requirements that are usually associated with “off-shore”.

I have been surprised and delighted with the level of work that our Costa Rican office produces and how seamlessly they integrate with our clients’ teams. I’m convinced that Nearshore is the best possible way to augment a local team.  I look forward to having this blog as a way to communicate our progress as a consultancy and to pass along technical information that is relevant.  Thank you for taking a look!

Welcome to the number8 Blog

Welcome to the Prosoft BlogHi there you,

We give you the warmest welcome to the number8 blog (previously Prosoft Nearshore). Our people have been working on posting important information on this blog, and we sincerely hope you will find this helpful.

Our Management and Technical Staff post here information relevant to their business domain, and that you can browse around by means of the Categories and Tags of each post.

Feel free to browse around, comment and provide us feedback about the topics and posts you find on our blog. And while you are at it, make sure you visit our web page (www.number8.com) if you are still wondering Who we are?, What we do? or How we do it?

Happy reading!

The number8 Team