Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Create Your Own Web Panel For Your Application

0.00/5 (No votes)
27 Jul 2013 1  
How to create a web panel for your application.

Introduction

In this tip, I will explain how to display your application things in your WebPanel.

The project contains:

  • WebPanel DLL - Contains class for starting your own web panel
  • Test Application - Simple application to test if WebPanel works
  • Htdocs folder - Contains a CMS to create your panel
  • MySQL dump - You need to import this dump file to your MySQL server to use CMS

Screenshot and Video

Test Application

Simple application to test if all works. WebService requires to start the application as administrator.

Form Code

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
 
    WebPanel MyWebPanel;
    public static int runningtime_seconds = 0;
    public static int MyCounter = 0;
    public static string MyText;
    public static List<User> Users;
    
    private void Form1_Load(object sender, EventArgs e)
    {
        Users = new List<User>();
        Users.Add(new User("Jon", 30, "United States"));
        Users.Add(new User("Mario", 20, "Italy"));
        foreach (User user in Form1.Users)
        {
        listBox1.Items.Add(user.Name);
        }
        //Start WebPanel on ip:port and authentication username password
        MyWebPanel = new WebPanel(IPAddress.Parse("127.0.0.1"), 
          8000, "admin", "password");
        //Add some event handler
        LoginValidator.OnLoginAttempt += 
        new LoginValidator.onLoginAttemptHandler(onLoginAttempt);
        WebPanel.AfterReceiveRequest += 
        new WebPanel.AfterReceiveRequestHandler(AfterReceiveRequest);
        WebPanel.OnException += new WebPanel.OnExceptionHandler(OnException);
        //Start webService
        MyWebPanel.Start(typeof(WebPanelHandler), typeof(IWebPanel));
    }
 
    void onLoginAttempt(object sender, bool response)
    {
        richTextBox1.BeginInvoke(new MethodInvoker(delegate() { 
          richTextBox1.AppendText("Login response: " + response + Environment.NewLine); }));
    }
 
    void AfterReceiveRequest(object sender, ref System.ServiceModel.Channels.Message request, 
         IClientChannel channel, InstanceContext instanceContext)
    {
        var action = OperationContext.Current.IncomingMessageHeaders.Action;
        var operationName = action.Substring(action.LastIndexOf("/") + 1);
        richTextBox1.BeginInvoke(new MethodInvoker(delegate() { 
          richTextBox1.AppendText(operationName + " invoked" + Environment.NewLine); }));
    }
 
    void OnException(object sender, Exception e)
    {
        MessageBox.Show(e.Message);
    }
 
    private void button1_Click(object sender, EventArgs e)
    {
        MyCounter++;
        label2.Text = "Value: " + MyCounter;           
    }
 
    private void timer1_Tick(object sender, EventArgs e)
    {
        runningtime_seconds++;
        label1.Text = "Running time: " + runningtime_seconds+" seconds";
        richTextBox1.ScrollToCaret();
    }
 
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        MyText = textBox1.Text;
    }
}

WebPanel Methods

Methods that will be invoked from the CMS.

public class WebPanelHandler : IWebPanel
{
  public int RunningTime()
  {
    return Form1.runningtime_seconds;
  }

  public int MyCounter()
  {
    return Form1.MyCounter;
  }

  public string MyText()
  {
    return Form1.MyText;
  }

  public void CloseApplication()
  {
    if (MessageBox.Show("Do you really want to close application?", 
        "Confirm", MessageBoxButtons.YesNo) == DialogResult.Yes)
    {
      Application.Exit();
    }
  }

  public string GetUserInfo(string username, string age)
  {
    if (username == "" && age == "")
      return null;

    foreach (User user in Form1.Users)
    {
      int uage = 0;
      int.TryParse(age, out uage);
      if (user.Name.ToLower() == username.ToLower() || user.Age == uage)
      {
        return "Name: " + user.Name + "<br>Age: " + 
        user.Age + "<br>Country: " + user.Country;
      }
    }
    return null;
  }
}

WebPanel interface

Contains method signatures.

[ServiceContract]
public interface IWebPanel
{
    [OperationContract]
    int RunningTime();
    [OperationContract]
    int MyCounter();
    [OperationContract]
    void CloseApplication();
    [OperationContract]
    string MyText();
    [OperationContract]
    string GetUserInfo(string username, string age);
}

DLL

Contains class to start the WebPanel.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Reflection;
 
namespace Web.Panel
{
    public class LoginValidator : UserNamePasswordValidator
    {
        public delegate void onLoginAttemptHandler(object sender, bool response);
        public static event onLoginAttemptHandler OnLoginAttempt;
        /// <summary>
        /// Handle WebPanel Login Event</summary>      
        /// <param name="userName">Username</param>   
        /// <param name="password">Password</param>   
        /// </summary>

        [System.Diagnostics.DebuggerHidden]
        public override void Validate(string userName, string password)
        {
            if ((userName != WebPanel.Username) || (password != WebPanel.Password))
            {
                if (OnLoginAttempt != null)
                    OnLoginAttempt(this, false);
 
                throw new SecurityTokenException();
            }
            else
            {
                if (OnLoginAttempt != null)
                    OnLoginAttempt(this, true);
            }
        }
    }
 
    public class WebPanel
    {
        private IPAddress IP;
        private int Port;
        public static string Username;
        public static string Password;
        public delegate void AfterReceiveRequestHandler(object sender, 
          ref Message request, IClientChannel channel, InstanceContext instanceContext);
        public static event AfterReceiveRequestHandler AfterReceiveRequest;
        public delegate void BeforeSendReplyHandler(object sender, 
          ref Message reply, object correlationState);
        public static event BeforeSendReplyHandler BeforeSendReply;
        public delegate void OnExceptionHandler(object sender, Exception e);
        public static event OnExceptionHandler OnException;
        /// <summary>
        /// initialize webService   
        /// <param name="Ip">Ip to bind</param>   
        /// <param name="port">Port to bind</param>   
        /// <param name="username">Set username</param>   
        /// <param name="password">Set password</param>      
        /// </summary>
        public WebPanel(IPAddress IP, int Port, string username, string password)
        {
            this.IP = IP;
            this.Port = Port;
            Username = username;
            Password = password;
        }
 
        /// <summary>
        /// Custom webService Behavior to log incoming/outgoing Method call/response
        /// </summary>     
        class webServiceEvent : IEndpointBehavior, IDispatchMessageInspector
        {
            public void AddBindingParameters(ServiceEndpoint endpoint, 
              BindingParameterCollection bindingParameters)
            {
            }
 
            public void ApplyClientBehavior
            (ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
            }
 
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, 
              EndpointDispatcher endpointDispatcher)
            {
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
            }
 
            public void Validate(ServiceEndpoint endpoint)
            {
            }
 
            public object AfterReceiveRequest(ref Message request, 
              IClientChannel channel, InstanceContext instanceContext)
            {
                if (WebPanel.AfterReceiveRequest != null)
                    WebPanel.AfterReceiveRequest
                    (this, ref request, channel, instanceContext);
 
                return null;
            }
 
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
                if (WebPanel.BeforeSendReply != null)
                    WebPanel.BeforeSendReply(this, ref reply, correlationState);
            }
        }
 
        /// <summary>
        /// Start WebPanel    
        /// </summary>     
        public bool Start(Type serviceType, Type implementedContract)
        {
            if (OnException == null)
            {
                throw new Exception("Assign a exception handler");
            }
 
            Uri baseAddress = new Uri("http://" + IP.ToString() + 
                ":" + Port + "/WebPanel/");
 
            // Create the ServiceHost. Bind on http://ip:port/WebPanel/
            ServiceHost selfHost = new ServiceHost(serviceType, baseAddress);
 
            //Binding to configure endpoint
            BasicHttpBinding http = new BasicHttpBinding();
 
            //Set a basic username/password authentication
            http.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
 
            http.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
 
            try
            {
                //Add the endpoint to the service host
                ServiceEndpoint endpoint = selfHost.AddServiceEndpoint(
                  implementedContract, http, "RemoteControlService");
                //Add the Custom webService Behavior to endpoint
                endpoint.Behaviors.Add(new webServiceEvent());
 
                //Set the custom username/password validation
                selfHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = 
                  UserNamePasswordValidationMode.Custom;
                selfHost.Credentials.UserNameAuthentication.
                CustomUserNamePasswordValidator = new LoginValidator();
 
                // Enable metadata publishing.
                ServiceMetadataBehavior smb = 
                selfHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null)
                {
                    smb = new ServiceMetadataBehavior();
                    smb.HttpGetEnabled = true;
                    selfHost.Description.Behaviors.Add(smb);
                }
 
                try
                {
                    //Start WebPanel
                    selfHost.Open();
                    return true;
                }
                catch (Exception e)
                {
                    if (e is AddressAccessDeniedException)
                    {
                        if (OnException != null)
                            OnException(this, e);
                        return false;
                    }
 
                    if (e is AddressAlreadyInUseException)
                    {
                        if (OnException != null)
                            OnException(this, e);
                        return false;
                    }
                }
            }
            catch (CommunicationException ce)
            {
                if (OnException != null)
                    OnException(this, ce);
                selfHost.Abort();
                return false;
            }
            return false;
        }
    }
}

CMS

Element Class

Generate the HTML code for the element.

<?php
class Element { 
  private $id;
  private $title;  
  private $methodname;  
  private $type;
  private $refreshrate;
  private $parameters;
  
  public function Element
  ($id, $title, $methodname, $type, $refreshrate, $parameters) {
    $this->id = $id;
    $this->title = $title;
    $this->methodname = $methodname;
    $this->type = $type;
    $this->refreshrate = $refreshrate;
    $this->parameters = $parameters;
  } 
  
  public function getHtml() {
    echo '<div class="box" style="margin:8px; 
    display:inline-block;"><div name="title">
    <h3 style="margin: 0; float:left;">'.
    $this->title .'</h3>';
    echo '<a href="deleteelement.php?id='.
    $this->id.'"><img style="margin-left: 2px; 
    float: right;" src="./images/delete.png">
    </img></a></div><br><br>';
    if($this->type == 0)
    {
      echo '<div id="' . 
      $this->methodname . 'result">';
      echo objectToArray(Invoke($this->methodname))
      [$this->methodname . "result"];
      echo '</div>';
    }
    if ($this->type == 1)
    {
      echo '<a href="?invoke=' . 
      $this->methodname . '"><button 
      type="button">Invoke</button></a>';
    }
    if ($this->refreshrate > 0)
    {
      echo '<script type="text/javascript">';    
      echo 'function ' . $this->methodname . '_read()
      {      
        var ' . $this->methodname .'xmlhttp = AJAX();
        
        ' . $this->methodname .'xmlhttp.onreadystatechange=function(){
        if(' . $this->methodname .'xmlhttp.readyState==4){
        var obj = jQuery.parseJSON(' . 
        $this->methodname .'xmlhttp.responseText);    
        document.getElementById("' . 
        $this->methodname . 'result").innerHTML= obj
        ["' . strtolower($this->methodname) .'result"];        
        setTimeout("' . $this->methodname .
        '_read()",' . $this->refreshrate * 1000 . ');
        }
        }
        ' . $this->methodname .'xmlhttp.open
        ("GET","panel.php?getmethod=' . 
        $this->methodname .'",true);
        ' . $this->methodname .'xmlhttp.send(null);

      }';  
      echo 'addLoadEvent(' . $this->methodname . '_read())';
      echo '</script>';          
    }
    if ($this->type == 2 && $this->parameters != "")
    {
      $parameter = explode(',', $this->parameters);
      
      foreach($parameter as $key) {
        if ($key != "")
        {
          echo $key . "<br>";
          echo '<input type="text" name="' . 
          $key . '" id="' . $key . '">';
        }
      }  
      echo "<button onClick='InvokeWithParameters
      (\"" . $this->methodname . "\",\"" . 
      $this->parameters . "\")' 
      type='button'>Invoke</button>";
      echo '<div id="' . 
      $this->methodname . 'result">';
      
      echo '</div>';
    }
    echo '</div>';
  }
}
?>

webServiceConnector

Connects to a webservice, invokes a method and returns its response.

<?php
//Connect to WebService
$client = new SoapClient("http://localhost:8000/WebPanel/?wsdl",array(
'login' => "admin", 'password' => "password"));

function Invoke($methodname)
{
    try 
    {         
        global $client;
        $response = $client->__soapCall($methodname,array());
        return $response;
    } 
    catch (SoapFault $exception)
    {
        trigger_error("SOAP Fault: 
        (faultcode: {$exception->faultcode}, faultstring:
        {$exception->faultstring})");
    }
}
function InvokeWithParameters($methodname, $parameters)
{
    try 
    {         
        global $client;        
    
        $temp = explode (',',$parameters,-1);
        foreach ($temp as $pair) 
        {
        list ($k,$v) = explode ('|',$pair);
        $pairs[$k] = $v;
        }        
    
        $array = array("parameters" => $pairs);
        
        $response = $client->__soapCall($methodname, $array);
        return $response;
    } 
    catch (SoapFault $exception)
    {
        trigger_error("SOAP Fault: 
        (faultcode: {$exception->faultcode}, faultstring:
        {$exception->faultstring})");
    }
}
function objectToArray($d) {
    if (is_object($d)) {
        // Gets the properties of the given object
        // with get_object_vars function
        $d = get_object_vars($d);
    }

    if (is_array($d)) {
        /*
        * Return array converted to object
        * Using __FUNCTION__ (Magic constant)
        * for recursive call
        */
        return array_change_key_case(array_map(__FUNCTION__, $d), CASE_LOWER);
    }
    else {
        // Return array
        return $d;
    }
}
?>

How to Setup CMS

  • Change MySQL connection parameters in /htdocs/mysql.php
  • Change your WebPanel ip:port and username, password in /htdocs/includes/webServiceConnector.php
  • Open web browser and head to yoursite/register.php and create admin account (delete register.php after)
  • Make login

Add a New Element to the WebPanel

  • Element title: Element name that will be displayed on WebPanel
  • Method name: The method name that you declared in IWebPanel. The CMS will invoke it and will display its response.
  • Type: "Show value" for method with text response, "Action" for a void method or "With parameters" for methods with parameters
  • Refresh every: Refresh element every x seconds (Only on "show value" element type)

Add a Web Panel to your Application

  • Add reference to WebPanel.dll
  • Add:
    using System.ServiceModel;
    using Web.Panel;
  • Create a WebPanel variable
    WebPanel MyWebPanel; 
  • Add the code to start the WebPanel in your method:
    //Start WebPanel on ip:port and authentication username password
    MyWebPanel = new WebPanel(IPAddress.Parse("127.0.0.1"), 
    8000, "admin", "changeme");
    //Add some event handler
    LoginValidator.OnLoginAttempt += new LoginValidator.onLoginAttemptHandler(onLoginAttempt);
    WebPanel.AfterReceiveRequest += new WebPanel.AfterReceiveRequestHandler(AfterReceiveRequest);
    WebPanel.OnException += new WebPanel.OnExceptionHandler(OnException);
    //Start webService
    MyWebPanel.Start(typeof(WebPanelHandler), typeof(IWebPanel));
  • Add events handler methods:
    void onLoginAttempt(object sender, bool response)
    {
        //Do something
    }
    
    void AfterReceiveRequest(object sender, ref System.ServiceModel.Channels.Message request, 
         IClientChannel channel, InstanceContext instanceContext)
    {
        //Do something
    }
    
    void OnException(object sender, Exception e)
    {
        //Do something
    }
  • Add WebPanelHandler class and its interface:
    public class WebPanelHandler : IWebPanel
    {
        //Add your methods    
    }
    
    [ServiceContract]
    public interface IWebPanel
    {
        //Add your methods signatures example:
        //[OperationContract]
        //int test();    
    }

Conclusion

Thanks for reading this tip, I hope you liked it!

Let me know if you have suggestions to improve it, I'll be happy to implement them.

History

  • Version 1.0 - 22/07/2013
  • 25/07/2013 - Added video and conclusion
  • 27/07/2013 - Added support for methods with parameters
  • 06/12/2014 - Text formatting

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here