Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Create your own web panel for your application

, 27 Jul 2013
Rate this:
Please Sign up or sign in to vote.
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 start 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 methods 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, invoke a method and return 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 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 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rogai Lorenzo
Student
Italy Italy

Comments and Discussions

 
GeneralMy vote of 5 PinmemberArash M. Dehghani28-Jul-13 10:44 
GeneralRe: My vote of 5 PinmemberRogai Lorenzo28-Jul-13 11:11 
GeneralMy vote of 5 PinmemberKyrosWeb22-Jul-13 11:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 28 Jul 2013
Article Copyright 2013 by Rogai Lorenzo
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid