Skip to content
This repository has been archived by the owner on Aug 10, 2022. It is now read-only.

Commit

Permalink
Update Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
geoperez committed Mar 3, 2017
1 parent 3646f6e commit 2e8ef3c
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 108 deletions.
89 changes: 58 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

# EmbedIO Extras

:star: *Please star this project if you find it useful!*

Additional Modules showing how to extend EmbedIO. Feel free to use these modules in your projects.

## Bearer Token Module
Expand All @@ -30,9 +32,64 @@ server.RegisterModule(new BearerTokenModule(basicAuthProvider, routes));
PM> Install-Package EmbedIO.BearerToken
```

## Json Server Module

Based on the [JsonServer's](https://github.com/typicode/json-server) project, with this module you are able to simply specify a
JSON file as a database and use standard REST methods to create, update, retrieve and delete records from it.

```csharp
// Create Webserver and attach Json's Server
var server = WebServer.Create("http://localhost:9696/");
server.RegisterModule(new JsonServerModule(jsonPath: Path.Combine(@"c:\web", "database.json")));
```

Supported methods:

* GET collection (//yourhost/entity)
* GET single (//yourhost/entity/1 where 1 is the ID)
* POST (//yourhost/entity with POST body the JSON object)
* PUT (//yourhost/entity/1 with POST body the JSON object)
* DELETE (//yourhost/entity/1 where 1 is the ID)

## LiteLib WebAPI

Similar to Json Server Module, but you can serve a sqlite file with all HTTP verbs.

```csharp
// Create Webserver and attach Json's Server
var server = WebServer.Create("http://localhost:9696/");
server.RegisterModule(new LiteLibModule<TestDbContext>(new TestDbContext(), "/dbapi/"));
```

Supported methods:

* GET collection (//yourhost/entity)
* GET single (//yourhost/entity/1 where 1 is the ID)
* POST (//yourhost/entity with POST body the JSON object)
* PUT (//yourhost/entity/1 with POST body the JSON object)
* DELETE (//yourhost/entity/1 where 1 is the ID)


### Nuget installation [![NuGet version](https://badge.fury.io/nu/EmbedIO.LiteLibWebApi.svg)](https://badge.fury.io/nu/EmbedIO.LiteLibWebApi)

```
PM> Install-Package EmbedIO.LiteLibWebApi
```

## Markdown Static Module

The Markdown Static Module takes in a static markdown file and converts it into HTML before returning a response.
It will accept markdown/html/htm extensions (This could become middleware later).

```csharp
// Create Webserver and attach Markdown Static Module
var server = WebServer.Create("http://localhost:9696/");
server.RegisterModule(new MarkdownStaticModule(@"c:\web"));
```

## OWIN Integration

EmbedIO can use the OWIN platform in two different ways:
The support to OWIN is not under development, and it may not work correctly. EmbedIO can use the OWIN platform in two different ways:

* You can use EmbedIO modules within an OWIN Server. In other words, host your application with an OWIN server and make use of EmbedIO modules.

Expand Down Expand Up @@ -131,33 +188,3 @@ public class Program
```
PM> Install-Package EmbedIO.OWIN
```

## Markdown Static Module

The Markdown Static Module takes in a static markdown file and converts it into HTML before returning a response.
It will accept markdown/html/htm extensions (This could become middleware later).

```csharp
// Create Webserver and attach Markdown Static Module
var server = WebServer.Create("http://localhost:9696/");
server.RegisterModule(new MarkdownStaticModule(@"c:\web"));
```

## Json Server Module

Based on the [JsonServer's](https://github.com/typicode/json-server) project, with this module you are able to simply specify a
JSON file as a database and use standard REST methods to create, update, retrieve and delete records from it.

```csharp
// Create Webserver and attach Json's Server
var server = WebServer.Create("http://localhost:9696/");
server.RegisterModule(new JsonServerModule(jsonPath: Path.Combine(@"c:\web", "database.json")));
```

Supported methods:

* GET collection (//yourhost/entity)
* GET single (//yourhost/entity/1 where 1 is the ID)
* POST (//yourhost/entity with POST body the JSON object)
* PUT (//yourhost/entity/1 with POST body the JSON object)
* DELETE (//yourhost/entity/1 where 1 is the ID)
156 changes: 80 additions & 76 deletions src/Unosquare.Labs.EmbedIO.LiteLibWebApi/LiteLibModule.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Threading.Tasks;
using Unosquare.Labs.EmbedIO.LiteLibWebApi;
using Unosquare.Labs.LiteLib;
using System.Reflection;
using Unosquare.Swan.Formatters;
using Unosquare.Labs.LiteLib;
using Unosquare.Swan;
using System.Collections;
using Unosquare.Swan.Formatters;
using Unosquare.Swan.Reflection;

namespace Unosquare.Labs.EmbedIO.LiteLibWebApi
{
/// <summary>
/// Represents a EmbedIO Module to create an automatic WebApi handler for each IDbSet from a LiteLib context.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <seealso cref="Unosquare.Labs.EmbedIO.WebModuleBase" />
public class LiteLibModule<T> : WebModuleBase
where T : LiteDbContext
{
internal class GenericLiteModel : ILiteModel
{
public long RowId { get; set; }
}

private readonly T _dbInstance;

/// <summary>
/// Initializes a new instance of the <see cref="LiteLibModule{T}"/> class.
/// </summary>
/// <param name="instance">The instance.</param>
/// <param name="basePath">The base path.</param>
public LiteLibModule(T instance, string basePath = "/api/")
{
_dbInstance = instance;
Expand All @@ -35,104 +36,105 @@ public LiteLibModule(T instance, string basePath = "/api/")
if (path.StartsWith(basePath) == false)
return false;
var parts = path.Substring(basePath.Length).Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var parts = path.Substring(basePath.Length).Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
var dbSetType = _dbInstance.GetType().GetTypeInfo().Assembly.GetTypes().FirstOrDefault(x => x.Name.Equals(parts[0], StringComparison.OrdinalIgnoreCase));
var dbSetType =
_dbInstance.GetType()
.GetTypeInfo()
.Assembly.GetTypes()
.FirstOrDefault(x => x.Name.Equals(parts[0], StringComparison.OrdinalIgnoreCase));
if (dbSetType == null) return false;
var table = _dbInstance.Set(dbSetType);
if (parts.Length == 1)
{
if (verb == HttpVerbs.Get)
switch (verb)
{
List<object> dataList = new List<object>();
var data = _dbInstance.Select<object>(table, "1=1");
foreach (var row in data)
{
case HttpVerbs.Get:
var dataList = new List<object>();
var data = _dbInstance.Select<object>(table, "1=1");
foreach (var row in data)
{
var item = Activator.CreateInstance(dbSetType);
((IDictionary<string, object>) row).CopyPropertiesFromDictionary(item, null);
dataList.Add(item);
}
context.JsonResponse(dataList);
return true;
case HttpVerbs.Post:
var body = (IDictionary<string, object>) Json.Deserialize(context.RequestBody());
var objTable = Activator.CreateInstance(dbSetType);
((IDictionary<string, object>)row).CopyPropertiesFromDictionary(objTable, null);
dataList.Add(objTable);
}
context.JsonResponse(dataList);
return true;
}
if (verb == HttpVerbs.Post)
{
var body = (IDictionary<string, object>)Json.Deserialize(context.RequestBody());
var objTable = Activator.CreateInstance(dbSetType);
body.CopyPropertiesFromDictionary(objTable, null);
body.CopyPropertiesFromDictionary(objTable, null);
_dbInstance.Insert(objTable);
_dbInstance.Insert(objTable);
return true;
return true;
}
}
if (parts.Length == 2)
{
if (verb == HttpVerbs.Get)
{
var data = _dbInstance.Select<object>(table, "[RowId] = @RowId", new { RowId = parts[1] });
var objTable = Activator.CreateInstance(dbSetType);
((IDictionary<string, object>)data.First()).CopyPropertiesFromDictionary(objTable, null);
context.JsonResponse(objTable);
return true;
}
if (verb == HttpVerbs.Put)
switch (verb)
{
var objTable = Activator.CreateInstance(dbSetType);
var data = _dbInstance.Select<object>(table, "[RowId] = @RowId", new { RowId = parts[1] });
((IDictionary<string, object>)data.First()).CopyPropertiesFromDictionary(objTable, null);
var body = (IDictionary<string, object>)Json.Deserialize(context.RequestBody());
body.CopyPropertiesFromDictionary(objTable, new string[] { "RowId" });
_dbInstance.Update(objTable);
case HttpVerbs.Get:
{
var data = _dbInstance.Select<object>(table, "[RowId] = @RowId", new {RowId = parts[1]});
var objTable = Activator.CreateInstance(dbSetType);
((IDictionary<string, object>) data.First()).CopyPropertiesFromDictionary(objTable, null);
context.JsonResponse(objTable);
return true;
}
case HttpVerbs.Put:
{
var objTable = Activator.CreateInstance(dbSetType);
var data = _dbInstance.Select<object>(table, "[RowId] = @RowId", new {RowId = parts[1]});
((IDictionary<string, object>) data.First()).CopyPropertiesFromDictionary(objTable, null);
var body = (IDictionary<string, object>) Json.Deserialize(context.RequestBody());
body.CopyPropertiesFromDictionary(objTable, new string[] {"RowId"});
return true;
}
_dbInstance.Update(objTable);
if (verb == HttpVerbs.Delete)
{
var data = _dbInstance.Select<object>(table, "[RowId] = @RowId", new { RowId = parts[1] });
var objTable = Activator.CreateInstance(dbSetType);
((IDictionary<string, object>)data.First()).CopyPropertiesFromDictionary(objTable, null);
return true;
}
case HttpVerbs.Delete:
{
var data = _dbInstance.Select<object>(table, "[RowId] = @RowId", new {RowId = parts[1]});
var objTable = Activator.CreateInstance(dbSetType);
((IDictionary<string, object>) data.First()).CopyPropertiesFromDictionary(objTable, null);
_dbInstance.Delete(objTable);
_dbInstance.Delete(objTable);
return true;
return true;
}
}
}
return false;
});
}

/// <summary>
/// Gets the name of this module.
/// </summary>
public override string Name => nameof(LiteLibModule<T>).Humanize();
}

public static class Extensions
internal static class Extensions
{
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}

public static int CopyPropertiesFromDictionary(this IDictionary<string, object> source, object target, string[] ignoreProperties)
internal static int CopyPropertiesFromDictionary(this IDictionary<string, object> source, object target,
string[] ignoreProperties)
{
Lazy<PropertyTypeCache> CopyPropertiesTargets = new Lazy<PropertyTypeCache>(() => new PropertyTypeCache());
var copyPropertiesTargets = new Lazy<PropertyTypeCache>(() => new PropertyTypeCache());

var copiedProperties = 0;

var targetType = target.GetType();
var targetProperties = CopyPropertiesTargets.Value.Retrieve(targetType, () =>
var targetProperties = copyPropertiesTargets.Value.Retrieve(targetType, () =>
{
return targetType.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.CanWrite && Definitions.AllBasicTypes.Contains(x.PropertyType));
.Where(x => x.CanWrite && Definitions.AllBasicTypes.Contains(x.PropertyType));
});

var targetPropertyNames = targetProperties.Select(t => t.Name.ToLowerInvariant());
Expand All @@ -142,11 +144,12 @@ public static int CopyPropertiesFromDictionary(this IDictionary<string, object>

var ignoredProperties = ignoreProperties?.Where(p => string.IsNullOrWhiteSpace(p) == false)
.Select(p => p.ToLowerInvariant())
.ToArray() ?? new string[] { };
.ToArray() ?? new string[] {};

foreach (var sourceKey in filteredSourceKeys)
{
var targetProperty = targetProperties.SingleOrDefault(s => s.Name.ToLowerInvariant() == sourceKey.Key.ToLowerInvariant());
var targetProperty =
targetProperties.SingleOrDefault(s => s.Name.ToLowerInvariant() == sourceKey.Key.ToLowerInvariant());
if (targetProperty == null) continue;

if (ignoredProperties.Contains(targetProperty.Name.ToLowerInvariant()))
Expand All @@ -163,11 +166,12 @@ public static int CopyPropertiesFromDictionary(this IDictionary<string, object>

var sourceStringValue = sourceKey.Value.ToStringInvariant();

if (targetProperty.PropertyType == typeof(Boolean))
if (targetProperty.PropertyType == typeof(bool))
sourceStringValue = sourceStringValue == "1" ? "true" : "false";

object targetValue;
if (Definitions.BasicTypesInfo[targetProperty.PropertyType].TryParse(sourceStringValue, out targetValue))
if (Definitions.BasicTypesInfo[targetProperty.PropertyType].TryParse(sourceStringValue,
out targetValue))
{
targetProperty.SetValue(target, targetValue);
copiedProperties++;
Expand All @@ -182,4 +186,4 @@ public static int CopyPropertiesFromDictionary(this IDictionary<string, object>
return copiedProperties;
}
}
}
}
2 changes: 1 addition & 1 deletion test/Unosquare.Labs.EmbedIO.Owin.Tests/EmbedioOwinTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void GetIndex()

var html = new StreamReader(response.GetResponseStream()).ReadToEnd();

Assert.IsNotEmpty(html, "Directoy Browser Index page is not null");
Assert.IsNotEmpty(html, "Directory Browser Index page is not null");
Assert.IsTrue(html.Contains("<title>Index of /</title>"), "Index page has correct title");
}
}
Expand Down

0 comments on commit 2e8ef3c

Please sign in to comment.