forked from intellifactory/sitelets
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests, cleanup, fixes, documentation (intellifactory#5)
* Added ANC test project (they throw runtime error) * Basic working tests * WIP * Added unittest project + WIP * WIP * Sitelet.Protect fix * WIP * Unit test WIP * Changed Router.Shift (working) + updated unit tests * Added infer tests * Added Sitelet.Sum tests (not working because of Sitelet.Shift) * Removed ToQuery/ToForm + IHttpContext WIP * Removed System.Uri usage + added IHttpRequest * IHttpRequest changes * Small fix in shift * Fixed HttpRequest.Form wrapping * add HelloWorld integration test * Removed some unnecessary comments + updated test (json test is WIP) * Added json api testing * Removed FSharp.SystemTextJson dependency from Sitelets * Added test categories to unittests * Added Sitelet.EmbedInUnion test * Added Sitelet.InferPartialInUnion test * Added Sitelet.Folder test and Sitelet.Empty draft (not sure if it is needed at all) * Added Sitelet.New test * Added Sitelet.Box/Unbox test * Added Sitelet.Map test * Added categories to integration test cases * Added template for remaining sitelet tests * Added JsonOptions to serializer * Added Sitelet.TryMap test * Json routing without thread blocking * Remove all Obsoleted API * Changed Sitelet.Protect logic, added authentication to the FSharp test project + added Sitelet.Protect test * Removed Sitelet.Protect test template from unit tests * Added Sitelet.InferPartial test + Sitelet.InferWithCustomErrors draft * Added Sitelet.Embed test * get rid of more System.Uri * Added WS.Web.Tests + WS.Sitelets.Tests, WIP * Removed migrated test project from solution, tests WIP * Removed for real (didn't save on earlier commit) * Readme WIP * Readme updated * CSharp tests updated * Readme updated Co-authored-by: András Jankó <[email protected]>
- Loading branch information
1 parent
41e96d2
commit c2c3ca1
Showing
145 changed files
with
84,232 additions
and
209 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,154 @@ | ||
# IntelliFactory.Sitelets | ||
|
||
`Sitelets` is an F#-based library, that provides abstractions for creating ASP.NET Core web applications. | ||
|
||
## Table of contents | ||
|
||
* [Installing](#installing) | ||
* [Using Sitelets](#using-sitelets) | ||
* [Working with other ANC web frameworks](#working-with-other-anc-web-frameworks) | ||
* [Contributing](#contributing) | ||
|
||
## Installing | ||
|
||
The easiest way to add Sitelets to your project is by using dotnet cli: | ||
|
||
``` | ||
dotnet add YOUR_PROJECTFILE package Sitelets | ||
``` | ||
|
||
or if you work in Visual Studio, search for Sitelets in Nuget and install it in your project! | ||
|
||
## Using Sitelets | ||
|
||
For example let's create an ASP.NET Core Mvc app and plug Sitelets into it to make a Hello World site: | ||
|
||
``` | ||
dotnet new mvc -lang f# -o MyMvcApp | ||
dotnet add MyMvcApp/MyMvcApp.fsproj package Sitelets | ||
``` | ||
|
||
For clarity, let's add a `MySitelets` folder in to project and create a `HelloWorld.fs` source file in it. Now for this site we only want to print the 'Hello World' text onto the page, only this much code will do the job: | ||
|
||
```fsharp | ||
module Hello | ||
open Sitelets | ||
type EndPoint = | ||
| HelloEndPoint | ||
let helloWorldSite = Sitelet.Content "/hello" EndPoint.HelloEndPoint (fun _ -> box "Hello World") | ||
``` | ||
|
||
We also have to plug the sitelet into the application pipeline. Go to `Startup.fs` and do this: | ||
|
||
```fsharp | ||
... | ||
app.UseAuthorization() |> ignore | ||
// plug sitelet in here for example | ||
app.UseSitelets(Hello.helloWorldSite) |> ignore | ||
app.UseEndpoints(fun endpoints -> | ||
... | ||
``` | ||
|
||
After a quick build and run, if you go to the `/hello` endpoint, you will see "Hello World" in the response. Now this example only shows how easy it is to grab the package and use it in project. Here's a glimpse of what makes Sitelets a powerful tool: | ||
|
||
```fsharp | ||
type Pizza = | ||
{ | ||
Customer: string | ||
Size: int | ||
} | ||
type EndPoint = | ||
| [<Method "GET"; EndPoint "/index">] Home | ||
| [<Method "GET"; EndPoint "/greet"; Query "firstname"; Query "lastname">] GreetPerson of firstname:string * lastname: string | ||
| [<Method "POST"; EndPoint "/order">; Json "pizza"] Order of pizza:Pizza | ||
let inferSitelet = | ||
Sitelet.Infer (fun ctx -> function | ||
| Home -> // some content | ||
| GreetPerson f l -> | ||
// example content with the query parameters | ||
sprintf "Hello %s %s" f l | ||
|> box | ||
// e.g /greet?firstname=John&lastname=Doe -> Hello John Doe | ||
| Order p -> // same as above but json comes in request body | ||
) | ||
``` | ||
|
||
Please check the [documentation]() for more information. | ||
|
||
## Working with other ANC web frameworks | ||
|
||
Sitelets is a layer of abstraction on top of ASP.NET Core so it can work with other F# web frameworks like Giraffe or Saturn for example. Let's take a look at a Giraffe app, for starters: | ||
|
||
``` | ||
dotnet new giraffe -o MyGiraffeApp | ||
dotnet add MyGiraffeApp/MyGiraffeApp.fsproj package Sitelets | ||
``` | ||
|
||
Let's add a sitelet that echoes what you write after the `/echo` endpoint | ||
|
||
```fsharp | ||
// --------------------------------- | ||
// Sitelet | ||
// --------------------------------- | ||
type Endpoint = | ||
| [<EndPoint "GET /echo">] Str of string | ||
let inferredSite = | ||
Sitelet.Infer (fun ctx -> function | ||
| Str str -> box str | ||
) | ||
... | ||
let webApp = | ||
choose [ | ||
GET >=> | ||
choose [ | ||
route "/" >=> indexHandler "world" | ||
routef "/hello/%s" indexHandler | ||
] | ||
SiteletHelper.sitelet inferredSite | ||
setStatusCode 404 >=> text "Not Found" ] | ||
``` | ||
|
||
Add the sitelet to the pipeline and we are done! | ||
|
||
## Sitelets in C# | ||
|
||
Although the focus is on the F# side, you can also use the Sitelets library in C# ASP.NET Core project. As an example: | ||
|
||
```cs | ||
public class TestSitelet | ||
{ | ||
public static Sitelet<object> S => | ||
new SiteletBuilder() | ||
.With("/hello", ctx => | ||
"Hello World from C#" | ||
) | ||
.Install(); | ||
} | ||
``` | ||
|
||
## Contributing | ||
|
||
If you find any faults, please [submit a ticket](https://github.com/intellifactory/sitelets/issues/4). | ||
|
||
It is an open source project so anyone is more than welcome to contribute but make sure to discuss the changes before opening a PR, otherwise it might get rejected. | ||
|
||
## Links | ||
|
||
* [Nuget](#TODO) | ||
* [Intellifactory](https://intellifactory.com/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net5.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\Sitelets\Sitelets.fsproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.Logging; | ||
using ANCCSharp.Models; | ||
using Sitelets; | ||
|
||
namespace ANCCSharp.Controllers | ||
{ | ||
public class HomeController : Controller | ||
{ | ||
private readonly ILogger<HomeController> _logger; | ||
|
||
public HomeController(ILogger<HomeController> logger) | ||
{ | ||
_logger = logger; | ||
} | ||
|
||
public IActionResult Index() | ||
{ | ||
return View(); | ||
} | ||
|
||
public IActionResult Privacy() | ||
{ | ||
return View(); | ||
} | ||
|
||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] | ||
public IActionResult Error() | ||
{ | ||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System; | ||
|
||
namespace ANCCSharp.Models | ||
{ | ||
public class ErrorViewModel | ||
{ | ||
public string RequestId { get; set; } | ||
|
||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace ANCCSharp | ||
{ | ||
public class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
CreateHostBuilder(args).Build().Run(); | ||
} | ||
|
||
public static IHostBuilder CreateHostBuilder(string[] args) => | ||
Host.CreateDefaultBuilder(args) | ||
.ConfigureWebHostDefaults(webBuilder => | ||
{ | ||
webBuilder.UseStartup<Startup>(); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"iisSettings": { | ||
"windowsAuthentication": false, | ||
"anonymousAuthentication": true, | ||
"iisExpress": { | ||
"applicationUrl": "http://localhost:10987", | ||
"sslPort": 44385 | ||
} | ||
}, | ||
"profiles": { | ||
"IIS Express": { | ||
"commandName": "IISExpress", | ||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
}, | ||
"ANCCSharp": { | ||
"commandName": "Project", | ||
"dotnetRunMessages": "true", | ||
"launchBrowser": true, | ||
"applicationUrl": "https://localhost:5001;http://localhost:5000", | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Sitelets; | ||
|
||
namespace ANCCSharp.SiteletsTest | ||
{ | ||
[EndPoint("{first}/{last}")] | ||
public class Name | ||
{ | ||
public string first; | ||
public string last; | ||
} | ||
|
||
[EndPoint("/person/{name}/{age}", "/person/{age}/{name}")] | ||
public class Person | ||
{ | ||
public Name name; | ||
public int age; | ||
} | ||
|
||
[Method("GET"), EndPoint("qperson/{name}")] | ||
public class QueryPerson | ||
{ | ||
public QueryName name; | ||
|
||
[Query] | ||
public int? age; | ||
} | ||
|
||
public class QueryName | ||
{ | ||
[Query] | ||
public string first; | ||
|
||
[Query] | ||
public string last; | ||
} | ||
|
||
public class TestSitelet | ||
{ | ||
public static Sitelet<object> S => | ||
new SiteletBuilder() | ||
.With("/hello", ctx => | ||
"Hello World from C#" | ||
) | ||
.With<Person>((ctx, person) => | ||
String.Format("<p>{0} {1} is {2} years old.</p>", person.name.first, person.name.last, person.age) | ||
) | ||
.With<QueryPerson>((ctx, person) => | ||
person.age.HasValue ? | ||
String.Format("<p>{0} {1} is {2} years old.</p>", person.name.first, person.name.last, person.age.Value) : | ||
String.Format("<p>{0} {1} won't tell their age.</p>", person.name.first, person.name.last) | ||
) | ||
.Install(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.HttpsPolicy; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Sitelets; | ||
|
||
namespace ANCCSharp | ||
{ | ||
public class Startup | ||
{ | ||
public Startup(IConfiguration configuration) | ||
{ | ||
Configuration = configuration; | ||
} | ||
|
||
public IConfiguration Configuration { get; } | ||
|
||
// This method gets called by the runtime. Use this method to add services to the container. | ||
public void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.AddControllersWithViews(); | ||
} | ||
|
||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | ||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||
{ | ||
if (env.IsDevelopment()) | ||
{ | ||
app.UseDeveloperExceptionPage(); | ||
} | ||
else | ||
{ | ||
app.UseExceptionHandler("/Home/Error"); | ||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. | ||
app.UseHsts(); | ||
} | ||
app.UseHttpsRedirection(); | ||
app.UseStaticFiles(); | ||
|
||
app.UseRouting(); | ||
|
||
app.UseAuthorization(); | ||
|
||
app.UseSitelets<object>(SiteletsTest.TestSitelet.S); | ||
|
||
app.UseEndpoints(endpoints => | ||
{ | ||
endpoints.MapControllerRoute( | ||
name: "default", | ||
pattern: "{controller=Home}/{action=Index}/{id?}"); | ||
}); | ||
} | ||
} | ||
} |
Oops, something went wrong.