.NET and Open Source: better together

RTur.net

  • Join Us on Facebook!
  • Follow Us on Twitter!
  • LinkedIn
  • Subcribe to Our RSS Feed

Building Widgets for BlogEngine.NET 3.3

Version 3.3 dropped user controls from BlogEngine and new widgets use Razor views instead. To start developing new widget, open source code in Visual Studio, navigate to BlogEngine.NET/Custom/Widgets in the solution explorer and add "Example" folder. If you run application and go to admin/custom/widgets, you'll see "Example" widget added to available widgets. You can even drag it to widget zone and save changes.

But because we don't have any code to support this widget, in the website you'll see an error instead of actual widget. It explains what file BlogEngine is looking for - "widget.cshtml" in that newly created folder.

So go back to Visual Studio and add widget.cshtml file. Here is a code for it:

@{
    var title = Model.Title;
}
<div class="widget tagcloud">
    <h4 class="widget-header">@title</h4>
    <div class="widget-content">
        This is an example. Widget ID is @Model.Id
    </div>
</div>

Few things to understand in this code. It is very simple standard Razor view and BlogEngine passes Model object into the view as one would expect. This is very simple object indeed, it has only 2 properties: Title and Id. If you save your code and reload website, you should see your widget in the sidebar in all glory.

The title is the name of your folder, in this case "Example". The Id created when you drag-and-dropped widget into widget zone. With XML provider, it added line to the widget zone file under app_data/datastore/widgets. With database provider, it would update a record in the table. So there is no mystery here.

Even with this little knowledge, you already can do some useful things. For example, most social sites provide some kind of code widgets you can copy/paste in your blog as HTML - you could add this code to widget.cshtml and be done. Also, BlogEngine exposes many useful objects and events and they all available to you in the server-side code block. The code below shows how you can easily output number of posts and blog title pulling data from server-side code.

@{
    var title = Model.Title;
    var postCnt = BlogEngine.Core.Post.ApplicablePosts.Count;
    var blogName = BlogEngine.Core.BlogSettings.Instance.Name;
}
<div class="widget tagcloud">
    <h4 class="widget-header">@title</h4>
    <div class="widget-content">
        <p>Posts in the blog: @postCnt</p>
        <p>Blog title: @blogName</p>
    </div>
</div>

Here what you should see in the browser now:

This lets you create many simple widgets, but often you would want to provide customization. For this, your widget needs settings. Currently, if you click on pencil icon in the widget admin, it will only let you change title. To add settings page, we need to add "edit.cshtml" to the Example folder. The name follows convention and is what BlogEngine expects to find. So in Visual Studio, add "edit.cshtml" with code as below:

<!DOCTYPE html>
<html>
<body class="widget-edit">
    <div class="widget-edit-commentlist">
        <form method="post">
            <div class="form-group">
                <label>Example setting</label>
                <input type="text" class="form-control" id="txt1" name="txt1" value="" />
            </div>
            <button type="submit" class="btn btn-success">@Resources.labels.save</button>
        </form>
    </div>
</body>
</html>

Now if you open settings page in admin, this will look like this:

So we got our setting, but it is kinda ugly. To fix, we need to include some styles:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="~/Content/bootstrap.min.css">
    <link rel="stylesheet" href="~/Content/font-awesome.min.css">
    <link rel="stylesheet" href="~/admin/themes/standard/css/styles.css">
</head>

And it looks much better now.

With visuals in place, next thing is to be able save this setting and read it back. Modify edit.cshtml to look like code below:

@using BlogEngine.NET.Custom.Widgets
@{
    var exampleSetting = "This is an example";
    var widgetId = Request.QueryString["id"];
    var settings = Common.GetSettings(widgetId);
    if (IsPost)
    {
        settings["examplesetting"] = Request.Form["txt1"];
        Common.SaveSettings(settings, widgetId);
        @:<script type="text/javascript">window.parent.toastr.success("Completed");</script>
    }
    if (settings != null && settings.Count > 0)
    {
        exampleSetting = settings["examplesetting"];
    }
}
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="~/Content/bootstrap.min.css">
    <link rel="stylesheet" href="~/Content/font-awesome.min.css">
    <link rel="stylesheet" href="~/admin/themes/standard/css/styles.css">
</head>
<body class="widget-edit">
    <div class="widget-edit-commentlist">
        <form method="post">
            <div class="form-group">
                <label>Example setting</label>
                <input type="text" class="form-control" id="txt1" name="txt1" value="@exampleSetting" />
            </div>
            <button type="submit" class="btn btn-success">@Resources.labels.save</button>
        </form>
    </div>
</body>
</html>

There few things to explain in this code. First of, we included custom/widgets namespace and introduced local variable "exampleSetting". This variable represents value we want to be able type in the textbox and save. We need to know widget ID to be able to save and retrieve settings for this widget, and ID always passed into edit page by BlogEngine  as query string (line #4), so we use it to get settings object (line #5). This object provided by BlogEngine, and we don't care where and how it saves our value as long as we can save and get it back.

Before we save settings, widget will be using declared in the line #3 as default. But if I click "save" button, the code in the "if (IsPost)" block will be executed (lines 8-10). This will take value fro texbox, save it and display confirmation message.

And I can use code similar to above to use this setting in my Example widget:

@using BlogEngine.NET.Custom.Widgets
@{
    var exempleSetting = "Default value";
    var settings = Common.GetSettings(Model.Id);
    if (settings != null && settings.Count > 0)
    {
        exempleSetting = settings["examplesetting"];
    }
}
<div class="widget example">
    <h4 class="widget-header">@Model.Title</h4>
    <div class="widget-content">
        <p>Setting value: @exempleSetting</p>
    </div>
</div>

Which suppose to produce output in the browser similar to the picture below.

The widget settings allows to save multiple values and use them to customize your widget with anything it needs, like width, height, number of items, color and so on.

This is the first tutorial on widgets to get you started. Next time we can check things like input validation and publishing to the gallery.

Example.zip (1.04 kb)

Tutorial - Building NivoSlider Extension (Part 4)

Creating NuGet Package

nuget-logoBlogEngine uses NuGet format for sharing extensions. NuGet package in a nutshell is a ZIP containing files you want to share with some metadata NuGet uses internally. The easiest way to create a package is to use Package Explorer. Download and install this small application on your local machine, then click to run as any regular Windows application. At the time of writing, I’m using Package Explorer version 2.0. More...

Tutorial - Building NivoSlider Extension (Part 3)

Data Persistence

db_1What we need next is to save metadata for each picture used by every slider, and also we need to be able to add and delete all these records. Extension settings are standard way of doing it in BlogEngine - you declare what kind of data you want to maintain, set initial values and first time extension runs it will instantiate settings object and save it on the back-end. To maintain these data, blogger goes to admin/extensions and clicks extension link in the right sidebar. This will load auto-generated form where settings can be edited. The code below would be sufficient: More...

Tutorial - Building NivoSlider Extension (Part 2)

Creating Repository

HTML code we added to site.master can be moved to user control (1), so we’ll need just drop control on the page and be done. But some new themes use Razor instead of WebForms – for those to work we can provide HTML helper (2) do the same thing control does for WebForms. And also we want slider be available in the posts and pages, for that functionality we’ll have to use extension (3). Having planned 3 distinct UIs, it makes sense to abstract common functionality and make UI as light as possible. So lets start by moving that hard-coded list of images into its own class. Open  ~/app_code/extensions folder and create new folder inside it called “NivoSlider”. Then add new class “Repository.cs” – here what it looks like: More...

Tutorial - Building NivoSlider Extension (Part 1)

Getting Started - Pure HTML Code

When I built theme for this site I used excellent Boldy theme as a template, and original theme has nice jQuery slider for a front page. I did not need it at the time, but later used it for another project and liked how simple and light-weight this slider is. In this tutorial we’ll transform NivoSlider into full-featured extension for BlogEngine.NET 2.5 and learn few tips and tricks along the way that will help you add useful functionality to your blog with no sweat. More...

Compiled Extensions in BlogEngine 1.5

image With BE.NET 1.5 release candidate out of the door, it is a good time to look at some of the new features. Most of them are small and incremental, but nevertheless are interesting. One such feature is support for compiled extensions. There are several reasons you want to compile extension rather than provide source code, such as security, protecting intellectual property, simplifying deployment (for large extensions) etc. If you find a reason to choose this route, this guide is for you. More...

Simple Widget Tutorial

feedj-6 Feedjit is a service that provides live traffic feed for your site. It is easy to set up – you copy chunk of HTML and insert it into your blog’s markup. That is, if you know HTML and used to editing files in your blog, which shouldn’t be a requirement for average blogger. This is why popular blog providers supply Feedjit widgets – so that blogger does not have to edit files by hand and FTP them to the host. In this little exercise we create such a widget for BlogEngine. More...

Writing extensions for BlogEngine 1.4 (part 4)

ex_5-4

Default admin interface for extensions in BlogEngine works fine in most cases and very easy to use. But sometimes you just got to get creative, right? That means, you want no limits. Obviously, some of simplicity will be lost – but still it is surprisingly easy to get along using plug-and-play BlogEngine architecture. Lets say, we ran into nice DHTML color picker and want to use it in the admin page for our extension. We want admin page look like this picture – it should allow us to enter a word, size and color. This values will be saved in the extension manager, so we don’t have to deal with databases or file system – usual BE stuff. And when you click “Color picker” button, nice color picker will show up and you can visually select value for a color. More...

Writing extensions for BlogEngine 1.4 (part 3)

Lets say we want to write an extension to track user activities on our site. Blogger should be able to set basic settings, for example choose to track  posts, pages or both. Then every time user requests post or page, we increment corresponding counter by one. Look at the picture above. Its clear that we need two sets of settings: one for post/page options and another to list user activity.

ext14-3-1

More...

Writing extensions for BlogEngine 1.4 (part 2)

In the first part, we wrote simple extension that changes case in the post to lower. Let’s say, we want user to decide show post in the lower or upper case. For this, we need to be able to maintain variable and let blogger change it’s value through admin interface. Normally, you would need to add a data access functionality for extension to handle this kind of operation, create admin form etc. BlogEngine uses Extension Manager to help make job a lot easier. Take a look at the code below. In the constructor, we subscribe to post serving event and then call InitSettings. There we create ExtensionSettings object, which can hold singe value (scalar) or/and table of values. In our case, we want it to hold single scalar value, so we set settings to scalar. We call our variable “Case” and initialize it with default value of “upper”, then call ExtensionManager.InitSettings and pass name of extension and settings object. More...