Apps

Apps in Weavy allow you to display rich interactive web content as tabs in Spaces. You can build a Weavy app from scratch or embed an existing web-app experience. Some of the built-in apps are the Posts and Files apps.

When developing a custom app you should do the following:

  • Create a class extending the App class
  • Add a Controller extending the AppController<TApp> class
  • Add View files (.cshtml)

Model

Your first step when developing a new app is to create a class extending App. A good convention to follow is placing your class in the Areas\Apps\Models folder. In the example below we are creating an app for iframing a web page into a Space.

using System;
using System.ComponentModel.DataAnnotations;
using System.Runtime.InteropServices;
using Weavy.Core.Attributes;
using Weavy.Core.Models;

namespace Weavy.Areas.Apps.Models {

    [Serializable]
    [Guid("336F0C5F-019E-459B-B79E-3DE8F56E8D56")]
    [App(Icon = "application", Name = "IFrame", Description = "Generic app for embedding a web page in a space.", AllowMultiple = true)]
    public class IFrameApp : App {

        [Required]
        [DataType(DataType.Url)]
        [Display(Name = "Frame source", Description = "Full url of the resource to embed including http(s)://")]
        [Uri(ErrorMessage = "Must be a valid and fully-qualified url.")]
        public string Src { get; set; }
    }
}

Class attributes

As shown above, apps must be decorated with the [Serializable] and [Guid] attributes.

Make sure to give your class a unique Guid, otherwise it will not be recognized by Weavy.

To further customize your app you can also decorate it with the [App] attribute. Some of the properties you can set are:

  • Icon – name of an icon to use when displaying the app.
  • Colorcolor to use for the icon.
  • Name – display name for the app, e.g. “IFrame”.
  • Description – a description to use for the app, e.g “Generic app for embedding a web page in a space”.
  • AllowMultiple – determines whether users can add multiple instances of the app to a space.
  • Content – list of content types allowed to be added to the app

Fields

App fields are pieces of information that can be added to an app. This can be useful if your app requires some kind of configuration or settings. App fields have a name and a type. In the example above, we added a field for storing the url of the web page to display in the iframe.

For a property to be considered an app field, it must be declared as public read-write, i.e. the property has the public access modifier and have both a get and a set accessor.

App fields must also have one of the following supported types:

  • enum
  • byte
  • short
  • int
  • long
  • bool
  • double
  • float
  • string
  • Guid
  • DateTime
  • TimeSpan

Nullables and Lists of the above types are also supported, e.g. int?, List<string> and List<DateTime?>.

Field attributes

By decorating your fields with one, or more, of the following attributes you can customize how the field is displayed, edited and/or validated.

Datatype

By default, Weavy will look at the property type (in this case string) when deciding which editor to use for the field. By decorating a field with the [DataType] attribute you can specify an additional type to associate with the field. This value will then be used by the UI to determine which editor to use for the field.

[DataType(DataType.Url)]
public string Src { get; set; }

Here we specify that the Src field should be treated as an url instead of a plain text string.

Display

The [Display] attribute lets you specify a name and description to use for the field.

[Display(Name= "Frame source", Description = "Full url of the resource to embed including http(s)://")]
public string Src { get; set; }
Validation

By adding one, or more, [Validation] attributes to your fields you can control how they are validated.

[Required]
[Uri(ErrorMessage = "Must be a valid and fully-qualified url.")]
public string Src { get; set; }

Here we specify that the Src property is required and that it must be a valid and fully qualified url.

For full control of validation you can let your class implement IValidatableObject and add your own validation logic.

Controller

Although creating the IFrameApp class is enough for Weavy to detect your app, without a custom Controller and View files it won’t be very useful. By extending the AppController<TApp> class you can hook into the rendering flow of your app and add your own custom logic. A good convention to follow is placing your controller classes in the Areas\Apps\Controllers folder.

Actions

The AppController<TApp> class has three virtual methods that you can override:

  • Weavy.Web.Controllers.AppController`1.Get – is executed when someone navigates to the app tab
  • Weavy.Web.Controllers.AppController`1.Edit – is executed when some wants to edit app settings
  • Weavy.Web.Controllers.AppController`1.New – is executed when adding a new app (tab) to a space

The code below shows what a controller for the IFrameApp could look like. Since this is a very simple app we can just return an ActionResult directly, but for a more complex app you could execute whatever custom logic you need before returning with return View(app). When you create a custom Controller and override one or more methods, you must also create the corresponding Views for the action methods.

using System.Web.Mvc;
using Weavy.Areas.Apps.Models;
using Weavy.Web.Controllers;
using Weavy.Core.Models;

namespace Weavy.Areas.Apps.Controllers {

    /// <summary>
    /// Controller for the <see cref="IFrameApp" />.
    /// </summary>
    [RoutePrefix("apps/{id:int}/336F0C5F-019E-459B-B79E-3DE8F56E8D56")]
    public class IFrameAppController : AppController<IFrameApp> {

        /// <summary>
        /// Display the specified url in an iframe.
        /// </summary>
        /// <param name="app">The app to display.</param>
        /// <param name="query">An object with query parameters for search, paging etc.</param>
        public override ActionResult Get(IFrameApp app, Query query) {
            // add custom logic here if needed...
            return View(app);
        }
    }
}

To avoid route conflicts, there is an important convention you should follow when adding an App controller. You should make sure your controller has a [RoutePrefix] attribute in the format apps/{id:int}/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX where the last segment is replaced with the Guid of your App, in this case 336F0C5F-019E-459B-B79E-3DE8F56E8D56 for the IFrameApp.

Additional actions

It is also possible to add custom action methods to your App controller just as you would in a standard ASP.NET MVC project. Here is a simple example just to show how easy it is.

/// <summary>
/// A test action to show that you can add custom actions to App controllers.
/// </summary>
/// <param name="id">Id of app</param>
[HttpGet]
[Route("test")]
public ActionResult Test(int id) {
    return Content("Test result");
}
Note that action urls must be specified via attribute routing with the [Route] attribute, and since we also have the [RoutePrefix] attribute on the Controller class the full url to the action above will be /apps/{id:int}/336F0C5F-019E-459B-B79E-3DE8F56E8D56/test.

Views

By adding custom View files (.cshtml) for your App, you can control how is is rendered. Your view files should be placed in a subdirectory under the Areas\Apps\Views folder matching the name of your Controller.

For the IFrameAppController that means you should add your view files in the Areas\Apps\Views\IFrameApp folder. And just as in any standard ASP.NET MVC project the name of your view file should match the corresponding Action. So, by adding a file called Get.cshtml to this folder you can control how Weavy will render the Get action of your controller.

  • Areas
    • Apps
      • Controllers
        • IFrameAppController.cs
      • Models
        • IFrameApp.cs
      • Views
        • IFrameApp
          • Get.cshtml

Here is an example view file that will display an <iframe> for the url specified in the Src field of the IFrameApp when navigating to the app tab.

@model IFrameApp
@{
    Title = Model.Name;
}

<iframe style="border:none;display:block;width:100%;height:100%;" src="@Model.Src"></iframe>
It’s a good idea to add the Weavy.Areas.Apps.Models namespace to your Views\Web.config file. Then you don’t have to include it with @using Weavy.Areas.Apps.Models in all your view files.