Vici MVC supports Ajax natively, meaning that you can use any server method from client (java)script simply by decorating a method with the [Ajax] attribute. This works in controllers, view components, forms and controls. The framework will automatically create the required javascript stubs and declarations in the rendered HTML, using an Ajax provider plugin. An Ajax provider plugin will call the server from client script and handle all the necessary plumbing.
One Ajax provider is included with Vici MVC:
If you use a different Ajax provider, you should specify the provider to use in the application's Init() method (the default is jQuery, so if you're using jQuery, you don't have to define an Ajax provider in your code)
public static void Init() { WebAppConfig.AjaxProvider = new MootoolsAjaxProvider(); }
Creating an ajax method is simple: just add the [Ajax] attribute to a method:
public class AjaxDemoController : Controller { public void Run() { } [Ajax] public static void GetItemCount(string filter) { return DataLayer.GetItemCount(filter); } }
You can then use this method from javascript:
<script> AjaxDemoController.GetItemCount("*" , function(result) { $("#ItemCount").text(result); }); </script>
(this example uses jQuery for DOM manipulation)
Ajax methods can only be called asynchronously ("in the background"). That's why you have to specify a callback function which will receive the return value of the ajax call as the first parameter.
You can optionally add a second callback function that will be called when an error occurred. The parameter passed to this callback function is an error message that was either generated by the javascript framework or the exception error message when an exception occurred in the server method.
For example:
<script> AjaxDemoController.GetItemCount("*" , function(result) { $("#ItemCount").text(result); } , function(errMsg) { alert(errMsg); } ); </script>
You are not limited to returning simple primitive types from Ajax methods. It's perfectly ok to return complex objects. You only have to keep in mind that all enumerable types (arrays, lists, ...) are returned as arrays, so if you return a generic list (List<>), you can't access any of the list's standard properties like Count or Capacity. You could
public class AjaxDemoController : Controller { public void Run() { //... } [Ajax] public static object GetItemInfo() { return new { LastUpdate = DateTime.Now, ActiveItems = DataLayer.GetActiveItems(), // returns a List<> InactiveItems = DataLayer.GetInactiveItems() // returns a List<> }; } }
(note: C# 3.0 anonymous objects are used in this sample)
Client-side javascript:
<script> function handleInfoResponse(info) { $("#LastUpdateSpan").text(info.LastUpdate); for (var i in info.ActiveItems) handleItem(info.ActiveItems[i]); // do something with the item for (var i in info.InactiveItems) handleItem(info.InactiveItems[i]); // do something with the item } AjaxDemoController.GetItemInfo(handleInfoResponse); </script>
The [Ajax] optionally accepts one parameter: the alias to use for the method in client script. By default, the name of the method is the namespace followed by the class name (controller name) and method name. This can become pretty long, so it's often better to rename the ajax method in javascript:
public class AjaxDemoController : Controller { public void Run() { // ... } [Ajax("ajaxItemCount")] public static void GetItemCount(string filter) { return DataLayer.GetItemCount(filter); } }
You can then use the shorter alias in javascript:
<script> ajaxItemCount("*" , function(result) { $("#ItemCount").text(result); }); </script>
In some cases you may want to return XML to the client from your ajax method. This can be useful if you are using a client framework that automatically intercepts XML (for example, the excellent Taconite plugin for jQuery). An ajax method that returns XML will pass a javascript XML document object to the callback function, not a string.
To tag an ajax method for XML, simply add the named parameter ReturnXml to the Ajax attribute and set it to true:
[Ajax(ReturnXml = true)] public string MyXmlAjaxMethod() { return "<?xml version=\"1.0\"?><taconite></taconite>"; }
You are not limited to using Ajax methods in controllers. Any form, custom control or view component can have Ajax methods.
Whenever a form, control or view component is rendered, the Ajax methods defined in these classes will be available in client-side javascript. The only restriction is that Ajax methods on forms, controls and view components should be declared as static, because the instance on which to act is not available once the view has been rendered to the client.
You can register any ajax method in the view by calling RegisterAjaxMethods() on the View object from your controller.
For example, let's say you have a class with a collection of ajax utility methods you want to use in your client code:
public static class AjaxTools { [Ajax] public static int GetFreeDiskspace() { return DiskspaceHelper.CalcFreeDiskspace() } [Ajax] public static string ResolveDomainName(string domain) { return IPHelper.ResolveDomain(domain); } }
In your controller, you can call:
View.RegisterAjaxMethods(typeof(AjaxTools));
or using the generic version:
View.RegisterAjaxMethods<AjaxTools>();