C# from 1.0 to 4.0 talk

Posted in Talks by bcardiff on the June 17th, 2009

On June 10th I had the chance to talk about the evolution the C# language had since its first RTM version.

This talk was in the context of the Microsoft academic program, here at Argentina, and took place at the UAI of Lomas de Zamora.

Although the talk lasted a couple of hours I think the slides are suitable for a crash course. Just to have a taste about syntax and things that C# team take care of during last years.

We have chance to see same nice Lambda expression things in C# 3.0 with sample of NetFX, Moq and Linq-to-SQL; and also some unit testing concepts (using Moq, of course)

Downloads:

RUN09: Jugando dentro del browser: AJAX Client Templates y jQuery en ASP.NET

Posted in ASP.NET MVC,Ajax,MSP,Talks,jQuery by bcardiff on the March 25th, 2009

Martín Salías and I participated at RUN09. The talk was named “Jugando dentro del browser: AJAX Client Templates y jQuery en ASP.NET”. We had the chance to show how Microsoft Ajax Client Templates works with JsonResult of ASP.NET MVC and jQuery datepicker plugin.

You can download the source code of the demo: run09-b1-sourcecode

Here are the resources we suggest to get started with all this:

ASP.NET MVC Guidelines: Notifications

Posted in ASP.NET MVC,Ajax,MSP by bcardiff on the March 11th, 2009

While developing a web application a developer should build some infrastructure for the whole system. ASP.NET MVC is not the exception. The fact that ASP.NET MVC is a framework, it doesn’t mean that covers 100% of the necessity a developer will have during the development, but it should let you fill the gap. This gap could be filled by third party libraries or just by something ad-hoc you develop.

I saw (and develop) some kind of notifications solutions in order to tell the user that something (good or bad) have just happened due to his action eg.: “your password has been changed”, “you have new messages”, etc. These implementations were constrained to the MVC-way, letting the model has a notification property, letting the view show that property, etc. They could, but as soon as you reach some Post-Redirect-Get, or some partial page AJAX call, or JSON AJAX call you will get into troubles.

Along this post I will show a notification solution that play nice with all these scenarios with a unify way. I don’t I’m telling something new here, just sharing the experience and thuoghts. I will assume that the notifications are plain strings, but it could be extended to include a kind field (info, warning, error).

Download sample code for ASP.NET MVC RC 2. Try test buttons and changing your password.

Interface

The first thing is how we expect to leave a notification. Since the notification capability should be used a lot I prefer to make them available without needing to change the Model or ActionResult, so lets create a INotificationService. In order to play nice with designs and testing prefer to let the controllers get a reference to:

public interface INotificationService
{
    void Send(string message);
}

How to use it

All the controllers should have HandleNotificationAttribute applied, later we will see what is this for. The controller that want to send a notification will need to get a reference to an INotificationService. During the execution of the action, the method Send could be called as many times as you want. You are able to return what ever ActionResult you want. But if doing a redirect, be sure to use a RedirectToRouteResult (i.e. suggesting ASP.NET MVC way to send HTTP Redirects).

[HandleNotification]
public class SomeController : Controller
{
    INotificationService notification;

    public SomeController(INotificationService notification)
    {
        this.notification = notification;
    }

    public ViewResult Index()
    {
        notification.Send("Welcome!");
        // Create some model for the view
        return View();
    }

    public ActionResult RedirectCall()
    {
        // Perform changes
        notification.Send("data saved");
        return RedirectToAction("Index", "Home");
    }

    public JsonResult JsonAjaxCall()
    {
        notification.Send("Lorem ipsum");
        notification.Send("dolor sit amet");
        return Json(new { A = 1, B = "lorem" });
    }

}

As it can be seen, it is straight forward the usage. The INotificationService only expose a method to add notification, but not to clear them.

Client side

Just for encapsulation I choose to create a ViewUserControl that it should be included at the MasterPage, or at every respose page of a non-AJAX HTTP Request.

<%@ Master ... %>
<%@ Register TagPrefix="core" TagName="notifications"
    Src="~/Core/Notifications/ShowNotifications.ascx" %>
<!DOCTYPE html PUBLIC ...>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <!-- ... -->
    <core:notifications runat="server" />
</head>
<!-- ... -->
</html>

The client side use Javascript to display notification, in the sample below I use jGrowl (and jQuery). It is easy to change it to generate some just plain divs inside an identified element if you prefer.

Somewhere in the code of ShowNotifications.ascx the following code defines how a notification is shown:

function showNotification(msg) {
    $.jGrowl(msg);
}

The HandleNotificationAttribute has the responsibility to expose the recent notifications in the way the ShowNotifications.ascx is expecting them.

The following section goes trough implementation details, which is not the most interesting part in the article.

How it works

I will detail how each scenarios is supported:

non-AJAX/non-redirect Actions

The action have just store some notifications. The HandleNotificationAttribute add to the ViewData a HandleNotificationInfo that the ShowNotifications.ascx will use to render some calls to the showNotification functions.

AJAX Actions (JSON or Partial View)

The JSON calls force us to send the notification out-of-the-band, I choose to use cookies. So, if the HandleNotificationInfo detects that the request is an AJAX request, it serialize the HandleNotificationInfo using JSON. The ShowNotifications.ascx attach to AJAX Complete event (using jQuery) and pulls recently added cookie, and remove it.

Up to this point the storage of the notifications (INotificationRepository) could be implemented inside the request life cycle, but in order to support the next scenario we will use an implementation of INotificationRepository that use the HTTP Session object.

Post-Redirect-Get

When the action tells the INotificationService to send a notification, it is stored (as in every call) using the INotificationRepository. In this case, the HandleNotification performs no action, remember it was a POST request. The client receives a Redirect which performs a GET that will fall in the previous cases. Since the INotificationRepository use HTTP Session object, upon the action executed by the GET is completed, the HandleNotification will perform the usual task: pop the stored notifications in INotificationRepository and expose them to the client.

A final remark is that since Attributes can’t be injected with dependencies I expose a static property that is set upon Application_Start, in Global.asax.

Hope you find it useful. I’m more interesting in the overall solution than in the actual implementation: that is, enhancing the ASP.NET MVC framework with some services you would need for a better application development.

Latam Windows Day – El futuro de la plataforma de desarrollo Web hoy

Posted in ASP.NET MVC,Ajax,MSP,Talks by bcardiff on the March 3rd, 2009

Today is the Windows Day event. With Sergio we are presenting some new features that will be part of ASP.NET 4.0 and other stuff:

  • ASP.NET MVC
  • Dynamic Data
  • Client Templates
  • IE Developers Tools
  • jQuery

First of  all a disclaimer is mandatory, the session was recorded during January, and as expected some improvements happened since that day:

  1. ASP.NET MVC move from Beta to RC (and to RC Refresh)
  2. IE8 move from Beta to RC
  3. jQuery move from 1.2.6 to 1.3.2 (with a brand new jQuery UI)

One the my preferred slides is the one where we compare ASP.NET WebForms with ASP.NET MVC:

ASP.NET MVC ASP.NET WebForms
URLs /Users/jdoe /UserProfile.aspx?id=jdoe
Testing straightforward not so easy
Markup full control always ViewState
User actions HTTP Request PostBacks
Request Life Cycle M – V – C PageLifeCycle
Integration with jQuery, Protoype, etc. 100% some dificulties
AJAX grained control UpdatePanel

This shows which thing you should have in mind if you are coming from WebForms in order to have a smooth transition to MVC.

Here are some resources:

Sergio will post in his blog the other demo.

You can leave comments and questions in this post or the one in windows day blog.

(Re)improved argument matchers in Moq

Posted in Moq by bcardiff on the February 23rd, 2009

In the past I wrote about MatcherAttibute in Moq allows developers to create quite easy argument matchers. Due to a suggestion, community opinions and Kzu‘s implementation, the matchers were improved again.

In an scenario with a Customer class and a IFooService:

   1:  public class Customer
   2:  {
   3:      public string Name { get; set; }
   4:      public int Age { get; set; }
   5:      // ...
   6:  }
   7:   
   8:  public interface IFooService
   9:  {
  10:      void Bar(Customer c);
  11:  }

If in a test you need an expectation on Bar method that stands for a Customer c where c.Age >= 18 you
needed to do something like this:

   1:  [Test]
   2:  public void Test1()
   3:  {
   4:      var mock = new Mock<IFooService>(MockBehavior.Strict);
   5:      mock.Setup(x => x.Bar(It.Is<Customer>(c => c.Age >= 18)));
   6:      // this will success
   7:      // mock.Object.Bar(new Customer { Age = 21 });
   8:      // this will fail
   9:      // mock.Object.Bar(new Customer { Age = 17 });
  10:  }

but from now on, using the Matcher factory the same expectation could be written as follows:

   1:  [Test]
   2:  public void Test2()
   3:  {
   4:      var mock = new Mock<IFooService>(MockBehavior.Strict);
   5:      mock.Setup(x => x.Bar(GrownUp()));
   6:      // this will success
   7:      // mock.Object.Bar(new Customer { Age = 21 });
   8:      // this will fail
   9:      // mock.Object.Bar(new Customer { Age = 17 });
  10:  }
  11:   
  12:  public static Customer GrownUp()
  13:  {
  14:      return Match<Customer>.Create(c => c.Age >= 18);
  15:  }

There is some tricky stuff around type here (returning a Match<T> in a method with return type). If you want to see how this work go to the code and read this discussion. All in all is to have a good experience with the compiler.

Continue to read the post and you will see some other alternatives!

Use property as matchers

Last sample could be rewritten with less parenthesis using property getters.

   1:  [Test]
   2:  public void Test2()
   3:  {
   4:      var mock = new Mock<IFooService>(MockBehavior.Strict);
   5:      mock.Setup(x => x.Bar(GrownUp));
   6:      // this will success
   7:      // mock.Object.Bar(new Customer { Age = 21 });
   8:      // this will fail
   9:      // mock.Object.Bar(new Customer { Age = 17 });
  10:  }
  11:   
  12:  public static Customer GrownUp
  13:  {
  14:      get { return Match<Customer>.Create(c => c.Age >= 18); }
  15:  }

More arguments

Also you could have more arguments involved in the matching, just add them as method arguments and use them in the lambda expression.
For example to match older than a certain age:

   1:  [Test]
   2:  public void Test3()
   3:  {
   4:      var mock = new Mock<IFooService>(MockBehavior.Strict);
   5:      mock.Setup(x => x.Bar(OlderThan(18)));
   6:      // this will success
   7:      // mock.Object.Bar(new Customer { Age = 21 });
   8:      // this will fail
   9:      // mock.Object.Bar(new Customer { Age = 17 });
  10:  }
  11:   
  12:  public static Customer OlderThan(int minimumAge)
  13:  {
  14:      return Match<Customer>.Create(c => c.Age >= minimumAge);
  15:  }

Your own helper class

To reuse some matchers, you could define them in a separate a class instead of inside the fixture.

   1:  [Test]
   2:  public void Test4()
   3:  {
   4:      var mock = new Mock<IFooService>(MockBehavior.Strict);
   5:      mock.Setup(x => x.Bar(An.OlderThan(18)));
   6:      // this will success
   7:      // mock.Object.Bar(new Customer { Age = 21 });
   8:      // this will fail
   9:      // mock.Object.Bar(new Customer { Age = 17 });
  10:  }
  11:   
  12:  static class An
  13:  {
  14:      public static Customer OlderThan(int minimumAge)
  15:      {
  16:          return Match<Customer>.Create(c => c.Age >= minimumAge);
  17:      }
  18:  }

Non static method

Finally, the matchers declaration and implementation don’t need to be static. So you could have additional context of matching.
Although I suggest this last only in certain scenarios, for example, match enumeration of values:

   1:  [Test]
   2:  public void Test5()
   3:  {
   4:      var mock = new Mock<IFooService>(MockBehavior.Strict);
   5:      var names = new E("John Doe", "Brian Cardiff");
   6:      mock.Setup(x => x.Bar(names.Some));
   7:   
   8:      // this will success
   9:      // mock.Object.Bar(new Customer { Name = "Brian Cardiff" });
  10:   
  11:      // this will fail
  12:      // mock.Object.Bar(new Customer { Name = "Sandy" });
  13:  }
  14:   
  15:  public class E
  16:  {
  17:      string[] names;
  18:      public E(params string[] names)
  19:      {
  20:          this.names = names;
  21:      }
  22:   
  23:      public Customer Some
  24:      {
  25:          get { return Match<Customer>.Create(s => names.Contains(s.Name)); }
  26:      }
  27:  }

More lines in matcher code

There is no need that the matcher code is a one-line lambda, in case you are not familiar writing lambdas, here is another sample:

   1:  [Test]
   2:  public void Test6()
   3:  {
   4:      var mock = new Mock<IFooService>(MockBehavior.Strict);
   5:      mock.Setup(x => x.Bar(Between(20, 30)));
   6:      // this will success
   7:      // mock.Object.Bar(new Customer { Age = 25 });
   8:      // this will fail
   9:      // mock.Object.Bar(new Customer { Age = 40 });
  10:  }
  11:   
  12:  private Customer Between(int from, int to)
  13:  {
  14:      return Match<Customer>.Create(c =>
  15:      {
  16:          if (c.Age < from)
  17:              return false;
  18:          if (c.Age > to)
  19:              return false;
  20:          return true;
  21:      });
  22:  }

Declarative jQuery (with Microsoft Ajax)

Posted in Ajax,jQuery by bcardiff on the December 3rd, 2008

Almost everybody likes jQuery, I’m one of them. Recently Microsoft publish Client Templates preview 3 which is a awesome client side template engine. One of the best aspects of Client Templates is it’s declarative syntax for attaching behaviors (Sys.UI.Behavior) to a DOM element.

Following I expose the plugin jquery.declarative which allows you to use in a declarative way another jQuery plugin.

N.B.: Along this post I will use a plugin called wajbar, which is near to be published in jQuery plugins directory.

You can download the source code here.

jQuery way

Usually jQuery plugins extend the jQuery interface in simple way:

$(<selector>).<method>(<options>)

for example:

<input type="text" maxlength="60" size="30" id="text1" />
<script type="text/javascript">
    $(function() {
        $('#text1').wajbar();
    });
</script>

Nothing wrong, but thing could turn ugly if you have a lot of plugins and components all around.

declarative way

In order to use a declarative syntax for a plugin named P, you have the following requirements:

  • jQuery core
  • Microsoft Ajax (MicrosoftAjax.js)
  • Microsoft Ajax Templates (MicrosoftAjaxTemplates.js)
  • jQuery Declarative plugin (jquery.declarative.js)
  • jQuery P plugin which should use syntax: $(<selector>).<method>(<options>);
  • Add xmlns:sys=”javascript:Sys” sys:activate=”*” attributes to your body tag.

Note: If you are using a ScriptManager you already have Microsoft Ajax. Microsoft Ajax Templates and jQuery Declarative plugin in must be referenced within the ScriptManager. Otherwise just include the references in that order.

After referencing, you would need to expose the plugin P to jquery.declarative:

//general syntax
// $.declare(<entry method name of P>);
$.declare('wajbar');

This is need just once, usually when DOM ready is ready.

Now, for using a wajbar you need to attach it.

<input type="text" maxlength="60" size="30" sys:attach="wajbar" />

That’s it. Have in mind that using multiple times jquery plugins will be less obstructive this way. No need for additional CSS classname or IDs for later selecting the desired element.

using arguments in plugin initialization

I mention before that jquery plugins usually supports options to be passed in initialization: $(<selector>).<method>(<options>);. For example the wajbar support passing a ‘submit’ property to indicate a DOM that should be disabled if the input value is longer than maxlength.

Given:

<input type="text" maxlength="20" size="40" id="text1" />
<input type="submit" value="submit" id="button1" />

using plain jQuery you would need to call

$('#text1').wajbar({submit: $('#button1')});

but the declarative alternative is now

<input type="text" maxlength="20" size="40"
   sys:attach="wajbar"
   wajbar:submit="{{ $('#button1') }}" />
<input type="submit" value="submit" id="button1" />

you can even get further and remove all the ids of your code and make them really reusable!

<input type="text" maxlength="20" size="40"
   sys:key="self"
   sys:attach="wajbar" 
   wajbar:submit="{{ $(self).next('input:submit') }}" 
/>
<input type="submit" value="submit" />

It’s a bit more complicated the last, but is 100% reusable. With sys:key attribute you said how you want to expose the current DOM element in the evaluation within {{ }}.

ajax partial page load

In order to use the declarative syntax in with partial page rendering you need to call

Sys.Application.processNode(<the new dom element>);

Either the partial page executes that or hook per ajax loaded content, this depends on site conventions.

more than one plugin

This new syntax allows more than one plugin, each with their initialization options. You just need to enumerate the plugins separated by a comma.

For example using the tagSuggestion plugin:

<script src="tag.js" type="text/javascript"></script>
<link href="tag.css" rel="stylesheet" type="text/css" /> <script type="text/javascript">
    $(function() {
        $.declare('wajbar');
        // fake suggestions
        setGlobalTags(['javascript', 'jquery', 'java', 'json']);
        $.declare('tagSuggest');
    });
</script>

Create an input with wajbar and tag suggestion:

<input type="text" maxlength="30" sys:attach="tagsuggest, wajbar" />

Note that the declarative names are lowercase always, no matter the case of the method name, since the namespaces are always lowercase.

PDC Essentials @ Buenos Aires

Posted in Talks by bcardiff on the November 12th, 2008

Updated November 20th, you can download slide and demos here.

On Tuesday 18th, Juan and I will be presenting ASP.NET 4.0 Roadmap. Check which other talks are available and register here.

This is the event information:

  • Horario: martes, 18 de noviembre de 2008 16:00 – 22:00 p.m.
  • Lugar: ITTC. Sarmiento 1113 Piso 5. Buenos Aires Argentina.
  • Registración
  • Descripción:Durante los días del 27 al 30 de Octubre se lleva a cabo la Professional Developer Conference en Los Angeles, Estados Unidos. Durante este evento Microsoft realiza grandes anuncios sobre novedades en la plataforma de desarrollo, presentando su visión de Cloud Computing, construyendo aplicaciones que desdibujan las barreras entre la PC, la Web y los dispositivos móviles, lo nuevo en VS 2010, .net Framework 4, distintos avances sobre Windows 7, la siguiente mayor versión de la plataforma cliente Windows y mucho más. En este evento, estaremos presentando algunas de las novedades develadas durante el evento, contando con disertantes asistentes al mismo.

jQuery for Script#

Posted in ASP.NET MVC,Ajax,Script#,jQuery by bcardiff on the November 7th, 2008

Quite a good title :-) . Some weeks ago I find the time to create proof of concept for that task: create a jQuery wrapper for Script#. The result is a partial wrapper that could be completed to support all in all jQuery functionality.

The main issues I encountered while developing were:

  • Write a Script# adapter
  • Adapt event handlers interfaces
  • Support jQuery overloads

At the same time I was learning a bit of Microsoft Ajax Client-Side Templates (preview 2), part of ASP.NET AJAX 4.0, which are not in preview 3 stage. I also had to to a minimal script# adapter for this, but it was totally ad-hoc.

Due to the dependence with Microsoft Ajax, aacorlib Script# engine is used, which doesn’t support some C# features like foreach.

Write a Script# adapter

First of all you need to read some Script#. Then need realize that anycode that depends on a Script# adapter is not testable unless you implement some basic behavior of the adapted component.

For example the wrappers usually returns null, or default(T), for a function that it’s return type is T.

jQuery use a fluent interface, so returning this instead of null
will allow a minimal chance be testable (to avoid spurious runtime null pointer exceptions.

Adapt event handlers interfaces

With jQuery an event handler is declared as follows:

var anchors = $("a");
anchors.click(function(){
    var target = $(this).attr('href');
    alert('anchor to ' + target + 'clicked.');
});

In C# the this keyword is binding to the current class, not as in Javascript. This force the full creation of a wrapper, previously I tried to just have a trivial wrapper with the ImportedAttribute
in every method, but wasn’t enough.

After some tweaks I finally got this to work:

jQuery anchors = jQueryApi.Select("a");
anchors.click(delegate(object sender){
    string target = jQueryApi.Select(sender);
    Script.Alert("anchor to " + target + "clicked.")
});

And the “implementation” magic code is:

public class jQuery {
    // ...
    public jQuery click(EventCallback fn){
        Script.Literal("{0}.click(function(){{ return {1}(this); }})", _jquery, fn);
        return this;
    }
}

Support jQuery overloads

In Script#, Javascript overloads are declared as extern
methods with AlternateSignatureAttribute
. What I try to get was a easy way to implement jQuery overloads. The
Function.apply
method was very useful.

In the following code it is shown how jQuery.attr methods are adapted, and how jQuery wrapper is maintained. It’s not very nice, but is what is needed to get this works.

public class jQuery
{
    [AlternateSignature]
    public extern string attr(string key);
    public jQuery attr(string key, string value)
    {
        object r = Script.Literal("{0}.attr.apply({0}, arguments)", _jquery);
        if (r == _jquery) // preserve jQuery wrapper
            return this;
        else
            return (jQuery) r; // cast for compilation, it will return corresponding type
    }
}

Sample Application

Doesn’t do much:

  1. Gets a hardcoded list of TODOs in JSON
  2. Unfold template using Client-Side Teamplates
  3. Add behavior to unfolded DOM

All this is implemented in Script# using an MVP pattern. Algo in Views/Tasks/Layout.aspx there is a commented Javascript implementation.

You can download the solution here.

Haskell Monads on the web

Posted in Functional Programming by bcardiff on the September 29th, 2008

Yesterday I spent some time reading about Haskell implementations of Monads because I want to prepare some exercise. I share some links and snippets.

  • http://www.haskell.org/tutorial/monads.html
  • http://www.haskell.org/haskellwiki/Monad
    • Laws & syntax
    • Monads in other languages
  • Philip Wadler / Monads
    • The essence of functional programming
      • This paper explores the use monads to structure functional programs. No prior knowledge of monads or category theory is required.
      • Monads increase the ease with which programs may be modified. They can mimic the effect of impure features such as exceptions, state, and continuations; and also provide effects not easily achieved with such features. The types of a program reflect which effects occur.
      • The first section is an extended example of the use of monads. A simple interpreter is modified to support various extra features: error messages, state, output, and non-deterministic choice. The second section describes the relation between monads and continuation-passing style. The third section sketches how monads are used in a compiler for Haskell that is written in Haskell.
    • Monads for functional programming
      • The use of monads to structure functional programs is described. Monads provide a convenient framework for simulating effects found in other languages, such as global state, exception handling, output, or non-determinism. Three case studies are looked at in detail: how monads ease the modification of a simple evaluator; how monads act as the basis of a datatype of arrays subject to in-place update; and how monads can be used to build parsers.
  • http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm
    • So far we’ve seen the monad concept applied to implicitly passing state. However monads can be used to implement several other programming features including: consuming input, producing output, exceptions and exception handling, nondeterminisim. To handle this variety, the basic operations of >>= and return are overloaded functions.
    • Monads and Software Engineering
      • The key to engineering a large software project is to make changes easy..
      • Monads can be used to make functional programs far more adaptable. You need to insert another processing step? Go right ahead, don’t worry about plumbing the state. You need another variable in the state? No problem, just change the underlying state and the basic members of the monad. You need to output messages from your computation? No problem, just change the monad to add an output string. You need to handle exceptions or nondeterminism? No problem, just change the monad.
      • It might be said that Haskell with monads does not give you much that you won’t find in an imperative, nondeterministic language, with extensible, strong, but generic typing, and a powerful applicative expression sublanguage. The problem is there is no such language in common use. Monads make up for many of the drawbacks of Haskell relative to imperative languages, but without giving up any of its strengths.
  • http://en.wikibooks.org/wiki/Programming:Haskell_monads
    • Simple example for generation random numbers with a seed.
  • http://logic.csci.unt.edu/tarau/research/PapersHTML/monadic.html
    • `monad-based’ approach to the definition of all-solution predicates in \lambdaProlog. As a follow-up, we obtain a clarification of Prolog’s high-order operators and their similarities and differences with monad comprehensions in functional languages.

Ajax Widgets with ASP.NET MVC Preview 3

Posted in ASP.NET MVC,Ajax by bcardiff on the July 21st, 2008

Since some time ago I’ve been working with ASP.NET MVC in a project for InSTEDD. The whole project includes quite a lot infrastructure (e.g.: little MVC projects that are plug-ins of the main website), but in this post I will try to show the approach we choose to accomplish Ajax Widgets that are governed by a controller. The design was also though to have a good developer experience (this mainly defines the signature of the ViewUserControls that represents the desired widgets). Also, two other goal were achieved, a) the first load of the page includes the widget rendering (so the user doesn’t need to wait longer than the main page loads), b) it is easy to notify the user about some actions: information, warnings and errors messages regarding the last action performed.

I’ve prepared a sample tagging application that runs with an in-memory storage. I will describe how the application works as a guidance for this post.

Download the source code

As you would expect I have an ItemsController which decides the Items to show (but only the items, not the tags).

image

A simple List view implementation for displaying the items would be as follows:

image

If now we want to add Tagging capability to this view, what should be developed? a) the View for displaying tags of each item, and b) a Controller to both perform actions and render the updated view.

Since in the List view of items the model are just items, without tags, to keep the view markup simple, and be easy to include the Tags Edit widget in any part an item is displayed the widget should inherit from ViewUserControl<Item>. (actually I’ve develop a base class for widgets: MvcWidget which I will introduce later). So, the final version of List view is as follows:

image

But if the Tags Edit widget has just an Item as model, how does the tags come from? Every ViewUserControl has a reference to the Controller through the ViewUserControl.ViewContext property. So we decide that the TagsController which will be the ajax endpoint, also is responsible for augmenting the Item with the list of tags. So the markup of the Tags Edit widget would be something like this:

image

I didn’t show the full source here to be more clear in the presentation (in the downloadable file the solution is complete of course). As you could see in the tooltip, the new Controller property of the view is strongly typed as TagsController. The view base class did that:

image

The final result will be that the root div (with class UpdatePanel) will be replaced upon an ajax request to the server. This could be done with your favorite JavaScript library (jQuery is mine). I’ve done some helper functions to treat link navigation and form submit to ajax request and perform UI update as needed.

A minimal TagsController implementation would be something like this:

image

Upon ajax request, Add and Remove methods will perform the appropriate actions in Repository and then Renders the Tags Edit view with an Item as a model, without tags, the same controller instance will be used to retrieve the tags for the item.

For the first load, we don’t have a TagsController instance, since the request was processed by a ItemsController. The MvcWidget class simply instantiate a TagsController for this case (of course, you should plug your DI framework here).

This depicts mostly the main design. To provide feedback to the user regarding the last action I implement two new kinds of ActionResult.

  • JavaScriptActionResult which renders a <script type=”text/javascript>…</script> element with a specified scripts.
  • CompositeActionResult which completes the ActionResult type hierarchy to implement a Composite pattern.

Also, ad-hoc for the site I implement ClientStatusActionResult which inherits from JavaScriptActionResult to have a nicer controller code. An implementation without error handling of the Add method could be like this:

image

I suggest to look at the downloadable source to get a better implementation with error handling. For example, the repository may throw an exception when the maximum amount of tags is exceeded, in this scenario a ClientStatusActionResult with ClientStatus.Error is returned in composition with the Tag Edit view as was submitted from the user.

BatchResults method is just a Controller extension method that returns a CompositeActionResult for the given argumetns.

jQuery runs the script element when it arrives from the server, so the JavaScript that update the status DOM element is execute.

A final note, the whole idea and implementation was a result of some pairing sessions with Juan Wajnerman.

Any kind of feedback is welcomed!

Next Page »