Ajax Widgets with ASP.NET MVC
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.
A simple List view implementation for displaying the items would be as follows:
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:
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:
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:
A minimal TagsController implementation would be something like this:
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.
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.