10 August 2018

.NET - HTTP server with TcpListener

It's easy to create a little web server using HttpListener, but it must run as administrator to listen to anything but the localhost. It can also be done with TcpListener, but it's somewhat trickier. The firewall will prompt to allow network access though, which the HttpListener won't, because it uses HTTP.SYS that listens on behalf of the application.

HttpServer class

private TcpListener Listener { get; set; }

public void Listen()
{
    Listener = new TcpListener(IPAddress.Any, 2000);
    Listener.Start();

    while (true)
    {
       var client = Listener.AcceptTcpClient();
       ThreadPool.QueueUserWorkItem((state) => Handle(client)); //Handle each request on it's own thread.
    }
}

private void Handle(TcpClient client)
{
    using (var io = client.GetStream())
    using (var reader = new StreamReader(io))
    using (var writer = new StreamWriter(io))
    {
        //Request
        string[] line = reader.ReadLine()?.Split(); //Do not read to end! It would hang.
        string method = line[0]; //GET, POST, ...
        string url = line[1]; //The requested URL.

        //Response
        string content = "<html><body>EGS</body></html>";
        writer.WriteLine("HTTP/1.1 200 OK");
        writer.WriteLine("Content-Type: text/html; charset=UTF-8");
        writer.WriteLine($"Content-Length: {content.Length}");
        writer.WriteLine("Connection: close");
        writer.WriteLine();
        writer.WriteLine(content);
    }

    client.Close();
}

Start the server

Server = new HttpServer();
new Thread(new ThreadStart(Server.Listen)).Start(); //On a separate thread, so the UI doesn't hang.

10 July 2018

C# - Retrieve objects from a database

Years ago, I wrote this stuff to facilitate working with a database. Recently, I augmented the Retrieve method by returning an IEnumerable of model objects instead of a DataTable. Kind of like LINQ does. Here is the method. Mind that it is built upon the earlier post.
public IEnumerable Retrieve(string query, params object[] parameters) where T : class
{
    using (var connection = new OdbcConnection(ConnectionString))
    using (var command = new OdbcCommand(query, Connection))
    {
        SetParameters(command, parameters);

        using (var reader = command.ExecuteReader())
        {
            var data = new List();
            var columns = new HashSet();

            while (reader.Read())
            {
                if (columns.Count <= 0)
                    for (int i = 0; i < reader.FieldCount; i++)
                        columns.Add(reader.GetName(i));

                var item = Activator.CreateInstance();

                foreach (var prop in typeof(T).GetProperties())
                {
                    if (!columns.Contains(prop.Name))
                        continue;

                    object value = reader[prop.Name];

                    if (value == null || value == DBNull.Value)
                    {
                        if (!prop.IsNullable())
                            prop.SetValue(item, default(T));

                        continue;
                    }

                    prop.SetValue(item, reader[prop.Name]);
                }

                data.Add(item);
            }

            return data;
        }
    }
}

09 July 2018

Extension - Create an enumerable from an object

The following is a simple little extension that takes an object, and returns an IEnumerable with that object as it's first and only element. I originally wrote it for a project called Cloud-X, and put it here as I included it in Project Hermes:
/// /// Takes an object af any type, and returns a list of that type with the object as it's first item.
/// public static IEnumerable ToEnumerable(this T firstItem) =>
  firstItem == null ? new List(0) : new List(1) { firstItem };

19 March 2018

XAML - markup extensions

Recently, I wanted to pass a boolean parameter to a value converter, but whatever you put there is passed as a string. That's when I discovered markup extensions. They allow you to pass a custom class with properties of any type to the value converter. This class is something like this:

sealed class BoolMarkupExtension : MarkupExtension
{
    public bool Value { get; set; }

    public BoolMarkupExtension() { }

    public BoolMarkupExtension(bool value)
    {
        Value = value;
    }

    public override object ProvideValue(IServiceProvider serviceProvider) => Value;
}

The value converter will receive what the ProvideValue method returns as parameter, so you can send the property or the class itself if it has multiple properties.

The value converter parameter can now be set to this class:

Visibility="{Binding IsPlaying, Converter={StaticResource BoolVisibilityConverter}, ConverterParameter={converters:BoolMarkup true}}"

01 February 2018

C# – Passing method delegates as arguments.

I wanted to pass a method to execute to a helper method that created a response on API requests. If the method succeeded, it should return it's result; if an exception was thrown, it should return a 500 with the error. This is what I came up with:

/// <summary>
/// For methods that don't have a return value.
/// </summary>
protected HttpResponseMessage Respond(HttpRequestMessage request, Action method,
          HttpStatusCode errorStatusCode, string errorMessage)
{
    try
    {
        method();
        return request.CreateResponse(HttpStatusCode.OK);
    }
    catch
    {
        return request.CreateErrorResponse(errorStatusCode, errorMessage);
    }
}

/// <summary>
/// For methods that do have a return value.
/// </summary>
protected HttpResponseMessage Respond(HttpRequestMessage request, Func method,
          HttpStatusCode errorStatusCode, string errorMessage)
{
    try
    {
        return request.CreateResponse(HttpStatusCode.OK, method());
    }
    catch
    {
        return request.CreateErrorResponse(errorStatusCode, errorMessage);
    }
}

Now, I can respond to an API request in a single line:

return Respond(Request, () => Repo.Update(c), HttpStatusCode.InternalServerError, "Failed!");