Archive for the ‘ASP.NET’ Category

Mailzor is a basic utility library to help generate and send emails using the Razor view engine to populate email templates, designed to be quickly pluggable into your .NET app.

In our applications we send out HTML formatted emails, and seed them with a variety of data. I thought it would be easy to write them as razor files (cshtml) and then use the razor engine to generate them and send.

It’s up on NuGet and with the release of v1.0.0.11, it’s more stable.

For the most up to date info follow along with the usage sections of the readme.md file on the github repository.

How it works

I thought I would share some background about the development of it, and hiccups along the way. The original set of code came from Kazi Manzur Rashid, which solved the problem of making use of System.Web.RazorTemplateEngine, which I extended (with permission) to be usable as an injectable dependency and via NuGet.

The core elements are, the creation and management of the SMTP client, the building up of the MailMessage. Then all the compilation related work to get the RazorTemplateEngine up and running.

The RazorTemplateEngine logic boils down to taking the razor file stored on disk and using CSharpCodeProvider.CompileAssemblyFromDom. So if you’re curious about this code in particular dig into EmailTemplateEngine.cs in the project files.

Prior to version .10 where I went down the path of using ilmerge to solve conflicts of version mismatch with System.Web.Razor.

It seems easy seeing how I took an existing chunk of operational code and extended, and it only seems easy when it is working, but when it doesn’t work and you’ve got strange compilation errors, debugging this mechanism is not the greatest. I found myself hunting for temporary files and trying to have other compiler flags to output more information.

In the early versions it was heavily the case of “works on my machine”, but now its fine and seems to be feature complete…

Objective

To halt processing of subsequent ajax calls after one causes an error.

Why

Any actions related to a similar set of data (or concept) will all go through the same queue. This way if something falls over during processing of any given request, halting the processing of further requests should help not worsen things, or at least avoid subsequent errors that are a direct result of the first error.

When something unexpected has happened it’s likely the underlying system data is not in a valid state. Further actions may complicate things, possibly making matters worse. But more likely further actions will also error and we shouldn’t subject the system to having to handle them. So the solution is to get the user to reload the application into a known good state, i.e. complete fresh request of data.

There’s a competing concern that particular user actions may be desirable to have processed even after particular unknown/unexpected errors occur, but for now we’re going to assume these are rarer and can be dealt with specifically simply by having them bypass this queue (or make use of an alternate queue).

How

A toggled case
– After an error set a flag that will keep prompting the user to reload the page after an error.

A fixed case
- Do not process items already queued up in the processing queue.

Queue entry management

This part is simple. Most of the code is plumbing around building up the ajaxQueue call.

#CoffeeScript
class ActionCommandQueue

    validState: true
    
    #todo: surface the console log issues to the user

    sendData: (url, data, type, settings) =>
        settings = settings || {}
        settings.url = url
        settings.data = JSON.stringify(data)
        settings.type = type
        settings.contentType = 'application/json; charset=utf-8'
        settings.error = @onError
        if @validState
            $.ajaxQueue(settings)
        else
            console.log "You need to reload the page to continue. (click here)."

    onError: (xhr, status, error) =>
        @validState = false
        console.log "Sorry that action failed. Please reload the page and try again"

Usage

    #CoffeeScript

    sendData '/api/Tasks', { description: "new task" }

http://api.jquery.com/queue/

The queue iteself

This part is also simple, seeing how the hard work in creating a jQuery .ajaxQueue() method has already been done by gnarf, and here’s the blog post outlining the code. This came out of a great stackoverflow answer and this one.

Except one modification

The .then( next, next ) call was replaced with a failure case, in production code it’s likely to be a silent failure because there’s an error handling function higher up in the call chain that will report the problem to the user (no need for repeating the message).

    function doRequest( next ) {

        fail = function () { console.log('cannot continue to process queue after an error');

        jqXHR = $.ajax( ajaxOpts )
            .done( dfd.resolve )
            .fail( dfd.reject )
            .then( next, fail /*was next*/ );
    }

An added benefit here is not just around safety for the error case, but this queue approach ensures important user actions will get dispatched and arrive in a correct order.

Example

Scenario
1. Create a Task.
2. Update task details
3. Add Sub Task
4. Edit Sub Task [Fails]
5. Some other action (possibly related to the sub task)
6. 7. 8. 9. all same as 5.

At step 4, it fails, because something prevented the sub task being added. But before Task 4 failed, the user also issued action 5 very quickly. Step 5 is what the above code is preventing from running because we’re not sure what the impacts may be.

Before I release some Unit Tests to demonstrate this. I have a crude annotation on the Chrome Developer tools console output. The proof is lack of calls to ‘doneCb‘ after the error. Note the 500 error, then the 2 error messages that follow.

Ajax Queue Drop

Chrome debug output showing the error output.

Queues, Deferred and Promises

It’s beyond the scope of what I wanted to talk about here, but the jQuery.ajax wrapper jQuery.ajaxQueue makes use of Deferred, Deffered.then() and Promises, they’re worth looking into to gain a detailed understanding. Some reading about the queue itself.

Conclusion

So now a user can click to their hearts content on a variety of partially related actions on a page, having each fire off an ajax() request. If something goes wrong they can be alerted, and you can save a flood of subsequent errors happening.

We’re getting close to pushing an application to a larger set of test users, and we’ll be interested in what happens when a larger variety of machine configurations (browsers and operating systems) and of course user actions encounter errors.

We started with simply catching any server side errors, and log them to a single database table (separate database to application).

To achieve this part of it, it is simple as having a very lightweight database connection mechanism to insert this log entry record, this way if there was an error with our applications standard database access mechanism we could also capture that.

In this fashion we can be reasonably sure that anything short of major production environment failure (network infrastructure / machine specific) that we’ll be able to capture errors while the system is being used. Those types of issues will be handled differently.

Then we realised it would be just as helpful to capture and store client side JavaScript errors in a similar fashion.

Capture

The JavaScript error handler looks like this, making use of window.error:

window.$debug.globalErrorHandler = function () {
  window.onerror = function (m, u, l) {
    
    $.ajax({
      url: '/Error/Occurred',
      type: 'POST',
      dataType: 'json',
      data: JSON.stringify({ errorMsg: m, url: u, line: l, uri: window.location.href }),
      contentType: 'application/json; charset=utf-8',
    });
    
    return true;
  };
};

An extra note here is I came across a JS library that offered a common ‘printStackTrace()’ method. Created by Eric Wendelingithub project. Which doesn’t work how I would have hoped it would have worked in our global error handler, but that’s the nature of the error handler event.

Never the less it does look quite helpful, to make use of it you need to have a specific try { } catch { } block around something that may fail. Checkout the readme on the github project page.

Back to the main focus of this post…

We can also decide to call $debug.globalErrorHandler() method in some central part of the web application, so that later it doesn’t have to be always turned on.

Receive

The MVC side of this is even simpler, since our users are logged in while using the application, we have ‘context’ information about them, so that’s one extra useful piece of information we can capture as part of the error.

public class ErrorController
{
  public void Occurred(ClientSideJavaScriptException error)
  {
    // this context in our application represents the user, so we know who experienced the error.
    error.User = _userContext.UserName;

    // we send this off elsewhere to be persisted, you could simply persist it here
    _service.Handle(error);
  }
}

The ClientSideJavaScriptException class simply has the properties required to send over the information from the ajax post.

public class ClientSideJavaScriptException
{
  public string ErrorMsg { get; set; }
  public string Url { get; set; }
  public string Line { get; set; }
}

Process

Finally the persistence logic here is via the Micro.ORM NPoco selected because Adam said it was good ;) and the Nuget Package helped.

//setup
Db = new Database("configuration_key_name");

Db.Insert(new Details
{
  OccurredWhere = "client-side-js",
  ExceptionMessage = errorDetails.ErrorMsg,
  When = DateTime.Now,
  StackTrace = errorDetails.Stack,
  Method = "Line Number:" + errorDetails.Line
}

Since I put “Legacy” in the post title to begin with, I would like to share some quotes from the often quoted Michael Feathers author of Working Effectively with Legacy Code. If you haven’t read it, you should – it comes highly recommended by many developers including Scott Hanselman on this Hanselminutes episode. But full disclosure I myself have only read a few random sections of it here and there.

Working Effectively with Legacy Code

What do you think about when you hear the term legacy code? If you are at all like me, you think of tangled, unintelligible structure, code that you have to change but don’t really understand. You think of sleepless nights trying to add in features that should be easy to add, and you think of demoralization, the sense that everyone on the team is so sick of a code base that it seems beyond care, the sort of code that you just wish would die.
–Feathers

This I strongly agree with, not to say that legacy code is always “unintelligible” or you want the code “to die”, but very often it requires a much larger unit of time to change when compared to more desirable (maintainable) code, which leads to this quote:

In the industry, legacy code is often used as a slang term for difficult-to-change code that we don’t understand.
–Feathers

This can be remedied in part by unit-tests…

Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.
–Feathers

That last quote from Feathers helps to outline my motives…

At my current place of employment we have a flagship application that was originally built using ASP.NET 1.1. Then slowly migrated to .NET framework 2.0 and then immediately converted for .NET framework 3.5. That task itself was not trivial, and now there is a new challenge to make the code more maintainable.

The legacy system was written in … but it worked, and it worked great … It was legacy because it wasn’t done with new and shiny…
–Hanselman

Hanselman makes a good point even though I paraphrased so it’s a more general statement. This applies to the application I’m working on improving. The application was in fact working “fine” in its .NET 1.1 form, but making changes/improvements was difficult. When I say difficult in this case I, in particular mean for new developers not familiar with the code base and application. Being the newest developer to work on this, I wanted the code base to improve so we could all make changes and improvements with confidence going forward.

This is the first in yet another series of posts from me. This series will focus on how we’ve gone about undertaking this migration. I’ll attempt to make each post stand reasonably alone to demonstrate migrating a specific application component from Web Forms to the Model-View-Presenter (MVP) pattern and in particular the Web Forms MVP framework.

Some of the objectives that we’re trying to achieve from this framework migration include:

blog.fossmo.net MVP diagram

This also leads down the path of improved development practices for the team:

silverbullet

So then what…

Web Forms by design does not lend itself to achieving all the objectives listed above and it is hoped that the use of the Web Forms MVP framework will take us down a better path. I say this with full understanding that there is no such thing as a Silver Bullet in software development, and that the adoption of a pattern and a supporting framework are just steps we are taking.

We’ve come this far in the post and I haven’t exactly outlined what Web Forms MVP is and why it’s our choice. So first, how about the obligatory pasting of the front page quote from the official project site:

The ASP.NET Web Forms MVP project is about bringing the love back to Web Forms through a renewed approach to using it – an approach that facilitates separation of concerns and testability whilst maintaining the rapid development that Web Forms was built to deliver.
WebFormsMVP.com

The choice to use Web Forms MVP as the framework to help us achieve the MVP pattern in our application, comes from the knowledge of successful implementations by Readify on large scale sites such as Grays Online. Along with an active community of developers working on the framework and its acceptance into the CodePlex Foundation.

Examples coming up…

Now that we’ve got the background and I’ve publicly committed to “better code” and “testable code”, the next post in this series will be about moving your OnLoad & Page_Load methods out of your code-behind files and some of the challenges.