At Calzada Media, we’ve used WebsitePanel as our hosting control panel for many years now. With only a few hiccups, it has done exactly what it says on the tin. What it doesn’t do is in anyway integrate with any of the other systems on our website like billing. Apart from the slight operational headache, this really doesn’t make for a great customer experience. The eventual aim is to produce a helper library that will bridge this gap.
Sandbox (aka Bash’n’Crash) installation of WebsitePanel
You will need access to a WebsitePanel instance. Unless you are supremely brave (and I’m not!) you should not use a production instance of WebsitePanel, but a bash’n’crash or sandbox installation.
My approach was to create a new Windows 2008 R2 virtual machine on my local Hyper-V server. This VM was then configured as a broad representation of one of Calzada’s hosting servers (IIS + MySQL + WebsitePanel). WebsitePanel was configured with the Portal listening on port 9001 and the EnterpriseServer on 9002. Custom rules were added to the Windows Firewall to allow remote access on both of these ports.
If you don’t want to go down the VM route, you can install WebsitePanel on your PC if it is capable of running IIS – typically Professional, Enterprise and Ultimate editions of Windows.
Required DLL files
Once you’ve installed WebsitePanel, you will need to copy three DLL files from c:\WebsitePanel\Portal\Bin into the bin directory of your ASP.net website:
Note: Although WebsitePanel uses Web Service Enhancements v3, you don’t need to install it on your development machine. Just including the DLL should be sufficient.
Connecting to the WebsitePanel API and getting a list of users
Connecting to the WebsitePanel is actually fairly easy. As WebsitePanel uses WSE3.0, not WCF, there is no need to create service references within Visual Studio – everything can be done programmatically.
1. In Visual Studio, create a new Web Form and paste the following code between the form tags
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="GetUsers.aspx.vb" Inherits="GetUsers" %>
<form id="form1" runat="server">
<td><asp:Button ID="btnReloadList" Text="Refresh" runat="server" /></td>
<td><asp:Literal ID="ltlResult" runat="server" /></td>
<td><asp:Literal ID="ltlError" runat="server" /></td>
The code behind should be
Partial Class GetUsers
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Protected Sub btnReloadList_Click(sender As Object, e As EventArgs) Handles btnReloadList.Click
Private Sub LoadUsersList()
' Assume User ID 1
' Create proxy configurator object
Dim config As New EnterpriseServerProxyConfigurator()
config.EnterpriseServerUrl = INSERT_WEBSITEPANEL_ENTERPRISESERVER_URL
config.Username = INSERT_WEBSITEPANEL_SERVERADMIN_USERNAME
config.Password = INSERT_WEBSITEPANEL_SERVERADMIN_PASSWORD
' Create & configure proxy object
Dim users As New WebsitePanel.EnterpriseServer.esUsers()
' Perform lookup
Dim lst As WebsitePanel.EnterpriseServer.UserInfo() = users.GetUsers(1, True)
gvUsers.DataSource = lst
Catch ex As Exception
ltlError.Text = ex.Message
' Clean up
' - little bit of paranoia
users = Nothing
config = Nothing
Note: If an exception occurs, the error message will be written to the ltlError usercontrol.
Notes & Comments
The username and password is sent in the clear (via the SOAP header). Whilst this is not necessarily an issue for development work, it is of considerable importance when considering API usage in a production environment. If you are going to access the API remotely, you should consider additional measures (SSL, Firewall rules etc) to protect the crucial serveradmin account details.
Unlike my experience with WCF web services, I have not had to make any alterations or tweaks to the web.config to cater for SOAP message sizes etc. The calls just seem to work.
The Website API Documentation is somewhat sparse. I got the above to work through a combination of trawling through forums and experimentation in Visual Studio. There are a whole range of API calls that are simply not documented – like Hosting Plans – that I will be covering in future posts.