Plugin Development Basics
Posted in Technical by JarrettV on 2/20/2010 12:05:31 PM - CSTThis tutorial will step you through the process of building a simple contact form plugin. This plugin will display a form on the page that will collect contact information. This plugin is included as a core plugin in version 1.4.
Step 1: Create the Input Form Widget
First, start by creating a model to hold the data for contact form (/plugins/Contact/ContactModel.cs):
public class ContactModel : BaseModel
{
public string EntryId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Message { get; set; }
}
This view model will be used to strongly type the data to the view.
Next, create a partial view that uses the above model to display the contact form (/themes/default/ContactWidget.ascx):
<%@ Control Language="C#" AutoEventWireup="true" Inherits="ViewUserControl<ContactModel>" %>
<div id="contact">
<h4>Send A Message</h4>
<form method="post" action="<%= Url.Action("SendMessage", "Contact") %>">
<fieldset>
<%= Html.Hidden("entryId", Model.EntryId) %>
<label for="name">Name <small>(required)</small></label><%= Html.ValidationMessage("name") %>
<%= Html.TextBox("name", Model.Name) %>
<label for="email">Email <small>(required)</small></label><%= Html.ValidationMessage("email") %>
<%= Html.TextBox("email", Model.Email) %>
<label for="phone">Phone</label><%= Html.ValidationMessage("phone") %>
<%= Html.TextBox("phone", Model.Phone) %>
<label for="message">Message <small>(required)</small></label><%= Html.ValidationMessage("message")%>
<%= Html.TextArea("message", Model.Message, 4, 100, null) %>
<%= Html.ValidationMessage("error") %>
<input type="submit" value="Send Message" />
</fieldset>
</form>
</div>
This form has inputs and validation messages for each of the fields. The submit button will post to the SendMessage action of the Contact Controller.
Step 2: Create the Controller
Create the controller to handle the display of the contact form widget and the post of the form data (/plugins/Contact/ContactController.cs). The the following Action method will display the contact form widget partial view:
public ActionResult ContactWidget(Include include)
{
ContactModel model = new ContactModel();
model.EntryId = EntryId.ToString();
return PartialView("ContactWidget", model);
}
Also create the action that will handle the form post:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SendMessage(ContactModel model)
{
LogService.Info("SendMessage");
ValidateContactModel(model);
if (this.ModelState.IsValid)
{
//TODO: support both ajax and full page
try
{
// get contact configuration
var contact = new ContactAppWorkspace(Workspace).Contact;
SendContactMessage(contact, model);
return PartialView("ContactSuccess", model);
}
catch (Exception ex)
{
LogService.Error(ex);
ModelState.AddModelError("error", "An unexpected error occured, please contact the webmaster.");
}
}
return PartialView("ContactWidget", model);
}
This method expects AJAX form posts but it can be expanded to use a full page if needed. Take a look at the source code to see the implementation of the ContactAppWorkspace, ValidateContactModel, and SendContactMessage.
When the user posts the form, if there are any errors, the form is returned with the errors displayed. If there are no errors, the success partial view is returned.
Step 3: Add Success View
Add the following code to a new partial view that accepts the strongly typed ContactModel from before (/themes/default/ContactSuccess.ascx):
<%@ Control Language="C#" AutoEventWireup="true" Inherits="ViewUserControl<ContactModel>" %>
<div id="contact">
<h4>Thank You!</h4>
<p class="response"><strong>Your message was sent successfully.</strong> We will get back to you as soon as possible.</p>
<p>
Name: <%= Model.Name %><br />
Email: <%= Model.Email %><br />
Phone: <%= Model.Phone %><br />
Message: <%= Model.Message %>
</p>
</div>
Step 4: Add Ajax and Style Assets
Let's add some jQuery that will turn our form into an AJAX post (/js/default/Contact.js):
$(document).ready(function () {
$('#contact form').live('submit', function () {
$.post($(this).attr('action'), $(this).serialize(), function (data) {
$("#contact").replaceWith($(data));
});
return false;
});
});
The above jQuery posts the form to the action and redisplays the response. Since it is using a live event, the submit function is rewired if the response contains the error form.
Let's add some style information to make the form look better (/css/default/Contact.css):
#contact label small {color:#666}
#contact input[type=text], #contact textarea {display:block; width:90%; margin-bottom:0.8em}
#contact input[type=text] {width:40%}
#contact .field-validation-error {color:#FF4444; margin-left:1em}
#contact .input-validation-error {color:#900; background-color:#FFDFDF}
#contact .response strong {color:#008800}
Step 5: Register Plugin
For the widget to be recognized, we need to register it as part of the plugin. Create the ContactPlugin that derives from Plugin (/plugins/ContactPlugin.cs):
public class ContactPlugin : BasePlugin
{
public ContactPlugin(ILogService logger) : base(logger) { }
public override void Register(IContainer container, List<SiteRoute> routes, ViewEngineCollection viewEngines, ModelBinderDictionary modelBinders, ICollection<Asset> globalAssets)
{
RegisterController<ContactController>(container);
RegisterCompositeWidget(container, "ContactWidget", "Contact", "ContactWidget", new string[] { "Contact.css", "Contact.js" });
}
}
This code notifies the plugin system that our plugin has a controller and a composite widget that calls the ContactWidget action in the ContactController. It also has two assets, Contact.css and Contact.js needed by the widget. These assets will get added to the page anytime this widget is used.
Step 6: Include the Widget into the Contact Page
We are ready to include the widget on our contact page. We will use the new inline-widget support to include the widget into the content of our page. Open the contact.xml file from the www pages collection and add the following include line (/App_Data/www/pages/contact.xml):
<svc:include name="ContactWidget" />
<atom:content type="xhtml">
<div>
<p>
You can contact me via email <strong><a href="mailto:admin@example.com">admin@example.com</a></strong> or feel free to leave a comment on my blog.
</p>
<svc:include name="ContactWidget" />
</div>
</atom:content>
This tells the system to include the widget into the content of the page.
You are done, you should now be able to view the contact form on the contact page. If there are errors, the form will redisplay with the error messages.
In the next part, we will look at adding configuration settings for this plugin to the AtomSite Manager.