unosquare / embedio

A tiny, cross-platform, module based web server for .NET
http://unosquare.github.io/embedio
Other
1.46k stars 176 forks source link

How to create a custom module #471

Closed madarax64 closed 4 years ago

madarax64 commented 4 years ago

Is your feature request related to a problem? Please describe. As it is, I'm trying to write a simple file upload handler. This fits more of a regular MVC pattern than a WebAPI, so I'm using a Module rather than a WebAPI controller. However, there's virtually no documentation on how Modules work - everything seems to be centered around WebAPIs, so its not clear how to write Actions (using the ASP.NET Term here for analogy) at all.

Describe the solution you'd like A simple example showing how to implement Controllers with simple Actions.

Thanks

rdeago commented 4 years ago

Hello @madarax64, thanks for using EmbedIO!

You're right, documentation is currently rather scarce about plain vanilla modules. I'll try to put you on the right track.

While a module is, theoretically, just a class that implements IWebModuleImpl (and of course IWebModule), in practice you'll be better off deriving your module from WebModuleBase.

Here's the skeleton of a very simple module:

using System;
using System.Threading.Tasks;
using EmbedIO;
using EmbedIO.Utilities;

namespace Example
{
    public class HelloModule : WebModuleBase
    {
        public HelloModule(string baseRoute)
            : base(baseRoute)
        {
        }

        public override bool IsFinalHandler => true;

        protected override async Task OnRequestAsync(IHttpContext context)
        {
            // context.RequestedPath is relative to the module.
            // Here we only want to handle the path specified in the constructor,
            // so if there is a sub-path just return 404.
            if (context.RequestedPath != WebPath.Root)
            {
                throw HttpException.NotFound();
            }

            // This module only supports GET requests.
            if (context.HttpVerb != HttpVerbs.Get)
            {
                throw HttpException.MethodNotAllowed();
            }

            // Greet the user.
            context.Response.ContextType = MimeType.PlainText;
            using (var writer = context.OpenResponseText(buffered=true))
            {
                await writer.WriteAsync("Hello!").ConfigureAwait(false);
            }

            // This is important!
            // If you omit this call, EmbedIO will send a 404 response,
            // because this module's IsFinalHandler property is true.
            // If it were false, omitting this call would cause EmbedIO
            // to go on enumerating installed modules in search of one
            // that satisfies the base route.
            context.SetHandled();
        }
    }
}

Obviously there are a gazillion more things that a module can do, but this one has all the basic pieces in place.

More useful stuff, in no particular order:

I hope this can help you have a shot at your first module. If you need more help, either comment here or join us on Slack.

madarax64 commented 4 years ago

Hello @rdeago , Thank you so much, this solves my problem perfectly. Do you want to consider adding this (beautiful!) example to the readme.md so its immediately clear to new users? Thanks again!