Snippet - MicroServer - MVC HTTP, DHCP, DNS, SNTP Server

I just posted MicroServer - MVC HTTP, DHCP, DNS, SNTP Server on Codeshare. Feel free to discuss and make suggestions here.

16 Likes

Looks really promising, but can you give us some inspiration as to what this can be used for?

@ njbuch - We are using it as a battery/ solar powered central connection point (the MicroServer) for several remote devices (cobra II mainboards) that are connecting to it via WiFi. In our particular application, these devices are carried into the field (where no/limited internet access is available), linked together wireless and then used to collect data and control a USB device. This MicroServer allows the remote devices to create their own autonomous network (sort of like a battery powered access point). The remote devices need to talk to one another so they sync up (get an ip address, configuration file, and set time) from the MicroServer. Once the team in the field is done they just bring the devices back into the office power them on and the data is then automatically synced back to our database. In future versions, it’s likely that when internet tethering is available the MicroServer can be used to also to sync remotely. This is why both DNS and NTP have the ability to relay. In addition, when changes in the field need to be made, we are using JQuery Mobile framework to host several status and configuration pages from the MicroServer. This way the team in the field can see what the remote devices are doing from a tablet.

The MVC style web server allows us to reuse a large portion of the controller code and web pages on both full MVC server and the MicroServer. Of course our code is dumbed down to only use .NETMF functions. The DHCP, DNS, and SNTP server feature allows it so we never have to hard code an ip address or modify a configure file, the remote devices bounce back and forth between the MicroServer autonomous network, and several office networks seamlessly.

When this project goes to full production it will allow us to create a single custom hardware platform (using a G400) that can act as both a MicroServer and client.

Overall, I think this project could be useful to anyone who wants an MVC style web server or needs to have devices talk directly to one another without the dependence of the internet.

6 Likes

Wow, that is amazing. I can’t wait to load it on my board and start using MVC pages just like at work. It sounds really promising.

I can only repeat what Terrence said: "Wow, that is amazing"
I can’t wait to try this as well!

Sytak, I guess your remote devices are communicating with the micro server via wireless? Or what technology?

@ terrence - Yes, for testing we are using RS21 modules and a tp-link battery powered access point. We have also used ad-hoc mode, but our limited testing doesn’t work with more then one client. My long term goal would be to use something like the RN171 module that can operate as both a client and access point (MicroServer). This way we could eliminate the travel access point from the process.

If anyone has a RS171 module they are looking to sell, I’m open to buying it.

RS21 - https://www.ghielectronics.com/catalog/product/282
RN171 https://www.ghielectronics.com/catalog/product/444

This version of the “View” Action results only allows you to use token replacement on static html pages. However, we are finding the use of these token replacement “viewdata” objects and JSON endpoints processed on the client side using jquery work pretty well together.

This doesn’t include the full Razor view engine. The file structure is the same though. Here is how the token engine works:

public class HomeController : Controller
    {
		// Any public IActionResult method inherited from Controller is made available as an endpoint
		public IActionResult Index(ControllerContext context)
        {
            string ipAddress = ServiceManager.Current.HttpService.InterfaceAddress.ToString();
            string port = ServiceManager.Current.HttpService.ActivePort.ToString();
            ViewData["IPADDRESS"] = string.Concat(ipAddress, ":", port);

            return View();
        }    

        public IActionResult GetHello(ControllerContext context)
        {
            string response = "<doctype !html><html><head><title>Hello, world!</title>" +
                "<style>body { background-color: #111 }" +
                "h1 { font-size:3cm; text-align: center; color: white;}</style></head>" +
                "<body><h1>" + DateTime.Now.ToString() + "</h1></body></html>\r\n";

            return ContentResult(response, "text/html");
        }
    }
}

Create the following index.html page in the following path \DOTNETMF_FS_EMULATION\WINFS\WebRoot\Views\Home


<!DOCTYPE html>
<html>
<head>
    <title>MicroServer Website</title>
    <meta name="author" content="" />
    <meta name="description" content="" />
</head>
<body>
    <div>
        <div>
            <h2>Welcome</h2>
            <p>
                This is a MicroServer web page built for Micro Framework (NETMF). Here is an example controller endpoints:          
            </p>
            <div>
                <ul>
                    <li><a href="http://[%IPADDRESS%]/home/gethello" target="_blank">GetHello</a></li>
                </ul>
            </div>
        </div>
    </div>
</body>
</html> 

2 Likes

Very impressive. It will be great programming with mvc pattern.

Keep us posted on your progress.

Terrence

Instead of the RN171 Module you can use the RN 171 XV on a GHI XBee Adapter Module

https://www.ghielectronics.com/community/codeshare/entry/927

@ RoSchmi - Thanks! I will check it out.

MicroServer is now available through Nuget at:
NuGet Gallery | MicroServer.ServiceManager 1.1.0

Start a new emulator console application, install MicroServer Service Manager package and create a Program.cs file with the following source code. After running the project you can access the controller endpoint by launching a web browser using: http://[emulatoripaddress]/example/gethello

PM> Install-Package MicroServer.ServiceManager


using MicroServer.Service;
using MicroServer.Net.Http.Mvc;
using MicroServer.Net.Http.Routing;

namespace MicroServer.Example
{
    public class RouteConfig : HttpApplication
    {
        public override void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute(
                name: "Default",
                regex: @ "^[/]{1}$",
                defaults: new DefaultRoute { controller = "example", action = "gethello", id = "" }
            );

            routes.MapRoute(
                name: "Allow All",
                regex: @ ".*",
                defaults: new DefaultRoute { controller = "", action = "", id = "" }
            );
        }
    }

    public class ExampleController : Controller
    {
       
        // Any public IActionResult method inherited from Controller is made available as an endpoint
        public IActionResult GetHello(ControllerContext context)
        {
            string response = "<doctype !html><html><head><title>Hello, world!</title>" +
                "<style>body { background-color: #111 }" +
                "h1 { font-size:3cm; text-align: center; color: white;}</style></head>" +
                "<body><h1>" + DateTime.Now.ToString() + "</h1></body></html>\r\n";

            return ContentResult(response, "text/html");
        }
    }

    public class Program
    {
        public static void Main()
        {
            using (ServiceManager Server = new ServiceManager(LogType.Output, LogLevel.Debug, @ "\winfs"))
            {
                //INITIALIZING : Server Services
                Server.InterfaceAddress = System.Net.IPAddress.GetDefaultLocalAddress().ToString();
                Server.ServerName = "example";
                Server.DnsSuffix = "iot.local";

                // SERVICES:  Enable / disable additional services
                Server.DhcpEnabled = false; // disabled by default as this could be disruptive to existing dhcp servers on the network.
                Server.DnsEnabled = true;
                Server.SntpEnabled = true;

                //SERVICE:  Enable / disable directory browsing
                Server.AllowListing = false;

                //SERVICE: DHCP
                Server.DhcpService.PoolRange("172.16.10.100", "172.16.10.254");
                Server.DhcpService.GatewayAddress = "172.16.10.1";
                Server.DhcpService.SubnetMask = "255.255.255.0";

                //SERVICES: Start all services
                Server.StartAll();
            }
        }
    }
}
3 Likes

@ sytak -
Hi!
Is there an example of POST action.
My code looks like this:


but I am getting argument null exception.

[12/21/2015 15:50:33] MicroServer.Net.Http.HttpService | Debug | Pipeline => OnClientRequest
    #### Exception System.ArgumentNullException - 0x00000000 (11) ####
    #### Message: 
    #### System.Collections.Hashtable::Contains [IP: 0009] ####
    #### MicroServer.Net.Http.Serializers.CompositeSerializer::Deserialize [IP: 000e] ####
    #### MicroServer.Net.Http.Messages.HttpMessageDecoder::TriggerMessageReceived [IP: 0037] ####
    #### MicroServer.Net.Http.Messages.HttpMessageDecoder::ProcessReadBytes [IP: 00bc] ####
    #### MicroServer.Net.Http.HttpService::OnClientConnected [IP: 0016] ####
    #### MicroServer.Net.Sockets.SocketListener+ClientConnectedEventHandler::Invoke [IP: a09c68d4] ####
    #### MicroServer.Net.Sockets.SocketListener::OnClientConnected [IP: 0009] ####
    #### MicroServer.Net.Sockets.SocketListener::OnSocket [IP: 004f] ####
    #### MicroServer.Net.Sockets.TcpListener::StartTcpListening [IP: 000f] ####
A first chance exception of type 'System.ArgumentNullException' occurred in mscorlib.dll
Pipeline => MessageFailure

Any suggestions?

@ sytak

Very cool project and runs really well, credit to you for such a well architected library.

One decent improvement for me (to allow the sending of large files) was to change the way the message encoder created the response stream.

By using a custom ‘multistream’ class you can merge the header response with a filestream and not have to read everything into a new memorysteam (which causes OOM’s on large files). The socket reads / sends directly from the filestream in chunks and I can read very large multi-megabyte files off the SD card and send them without issue.

I am also adding a websocket ‘module’ but this is a little tricky due to the nature of the socket remaining open and still wanting to process further connections as the HttpMessageDecoder is not thread safe. If I make it work would you be interested in a pull request to your GitHub repo ??

Thanks again for your efforts with this great project

1 Like

@ sh

Yes it would be great if you would be willing to make a pull request on the repo. I would love to included any improvements you might have including a websocket module. Merging the headers response would be much more efficient.