Skip to content

Commit a86eba3

Browse files
committed
Merge pull request #15 from glennblock/dev
Big updates for Web API 2
2 parents c6303a4 + dd67b04 commit a86eba3

13 files changed

+489
-139
lines changed

README.md

+31-48
Original file line numberDiff line numberDiff line change
@@ -8,70 +8,53 @@ Makes using ASP.NET Web API's self host with scriptcs easy as cake, much easier
88

99
## Highlights:
1010

11-
* Creates a pre-configured self host with the default route already added.
12-
* Configures to allow resolving script controllers.
11+
* Creates a pre-configured OWIN self host with the default routes already added.
12+
* Supports configuring the OWIN pipeline
13+
* Write your controllers as scripts
1314
* Automatically imports common web api namespaces for you.
14-
* Works as self hosted server or in OWIN
1515

1616
## Getting started with Web API using the pack
1717

18-
Disclaimer: Ultimately (soon) you will be able to install this via nuget and not have to clone / build / copy
19-
2018
* Create a new folder for your script i.e. c:\hellowebapi and change to it.
21-
* Install the Web API script pack ```scriptcs -install -pre ScriptCs.WebApi```
19+
* Install the Web API script pack ```scriptcs -install -pre ScriptCs.WebApi2```
2220
* Create a start.csx and paste the code below
2321

2422
```csharp
25-
public class TestController : ApiController {
26-
public string Get() {
27-
return "Hello world!";
28-
}
23+
using System.Dynamic;
24+
25+
public class TestController : ApiController
26+
{
27+
public dynamic Get() {
28+
dynamic obj = new ExpandoObject();
29+
obj.message = "Hello from Web Api";
30+
return obj;
31+
}
2932
}
3033

31-
var webApi = Require<WebApi>();
32-
var server = webApi.CreateServer("http://localhost:8080");
33-
server.OpenAsync().Wait();
34-
34+
var webapi = Require<WebApi>();
35+
36+
var server = webapi.
37+
Configure(typeof(TestController)).
38+
UseJsonOnly().
39+
Start("http://localhost:8080");
40+
3541
Console.WriteLine("Listening...");
3642
Console.ReadLine();
37-
server.CloseAsync().Wait();
43+
server.Dispose();
3844
```
39-
* Running as admin type ```scriptcs start.csx``` to launch the app.
45+
* Running as admin type ```scriptcs start.csx -modules mono``` on Windows or ```scriptcs start.csx``` on Mac/Linux to launch the app.
4046
* Open a browser to "http://localhost:8080/api/test";
4147
* That's it, your API is up!
4248

43-
Alternatively you can host the script pack in OWIN e.g.
44-
45-
```csharp
46-
public class TestController : ApiController {
47-
public string Get() {
48-
return "Hello world!";
49-
}
50-
}
51-
52-
Require<OwinSelfHost>();
53-
54-
var webApi = Require<WebApi>();
55-
var config = webApi.Create();
56-
57-
using ( OwinSelfHost.CreateServer("http://localhost:8080", app => app.UseWebApi(config)) ) {
58-
Console.WriteLine("Listening...");
59-
Console.ReadLine();
60-
}
61-
```
62-
63-
6449
## Customizing
65-
You can customize the host by modifying the configuration object.
66-
Or if you would like to pass your own you can use the `CreateServer` overload.
67-
Additional `CreateServer` overloads allow you to explicitly specify assemblies or `IHttpController` types you want to expose in your api:
68-
50+
You can configure the OWIN host by passing in an `Action<IBuilder>` to the `Configure` method
6951
```csharp
70-
// Use a custom configuration and specify controller types.
71-
var config = new HttpSelfHostConfiguration("http://localhost:8080");
72-
var controllers = new List<Type> { typeof(TestController) };
73-
var server = webApi.CreateServer(config, controllers)
52+
var server = webapi.
53+
Configure(
54+
typeof(TestController),
55+
builder=> {
56+
builder.Use<MyMiddleware>();
57+
}
58+
).
59+
Start("http://localhost:8080");
7460
```
75-
76-
## What's next
77-
TBD

samples/formatter.csx

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Dynamic;
2+
using System.Web.Http;
3+
using System.Web.Http.Routing;
4+
5+
public class TestController : ApiController
6+
{
7+
public dynamic Get() {
8+
dynamic obj = new ExpandoObject();
9+
obj.message = "Hello from Web Api";
10+
return obj;
11+
}
12+
}
13+
14+
var webapi = Require<WebApi>();
15+
16+
var formatter = webapi.NewFormatter().
17+
SupportMediaType("application/vnd.foo+json").
18+
MapUriExtension(".foo", "application/vnd.foo+json").
19+
WriteToStream(async (args) => {
20+
var writer = new StreamWriter(args.Stream);
21+
await writer.WriteLineAsync("{\"foo\":\"foo\"}");
22+
await writer.FlushAsync();
23+
}).
24+
Build();
25+
26+
var config = new HttpConfiguration();
27+
28+
webapi.
29+
UseJsonOnly().
30+
Configure(config, typeof(TestController));
31+
32+
config.Formatters.Insert(0, formatter);
33+
34+
config.Routes.Clear();
35+
config.Routes.MapHttpRoute(name: "Extension",
36+
routeTemplate: "api/{controller}.{extension}/{id}",
37+
defaults: new {id = RouteParameter.Optional}
38+
);
39+
40+
var server = webapi.Start("http://localhost:8080");
41+
42+
Console.WriteLine("Listening...");
43+
Console.ReadLine();
44+
server.Dispose();
45+
46+

samples/packages.config

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<packages>
3+
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.0" targetFramework="net45" />
4+
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.0" targetFramework="net45" />
5+
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.0" targetFramework="net45" />
6+
<package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.0" />
7+
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
8+
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net40" />
9+
<package id="Microsoft.Net.Http" version="2.2.22" targetFramework="net45" />
10+
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net45" />
11+
<package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net45" />
12+
<package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net45" />
13+
<package id="Newtonsoft.Json" version="6.0.2" targetFramework="net45" />
14+
<package id="Owin" version="1.0" targetFramework="net40" />
15+
<package id="ScriptCs.Contracts" version="0.10.0" targetFramework="net45" />
16+
<package id="ScriptCs.WebApi2" version="1.0.0" targetFramework="net45" />
17+
</packages>

src/ScriptCs.WebApi/Formatter.cs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System;
2+
using System.IO;
3+
using System.Net;
4+
using System.Net.Http;
5+
using System.Net.Http.Formatting;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace ScriptCs.WebApi
10+
{
11+
internal class Formatter : MediaTypeFormatter
12+
{
13+
private Func<Type, bool> _canReadType;
14+
private Func<Type, bool> _canWriteType;
15+
private Func<ReadFromStreamArgs, Task<object>> _readFromStream;
16+
private Func<WriteToStreamArgs, Task> _writeToStream;
17+
18+
public Formatter(
19+
Func<Type, bool> canReadType,
20+
Func<Type, bool> canWriteType,
21+
Func<ReadFromStreamArgs, Task<object>> readFromStream,
22+
Func<WriteToStreamArgs, Task> writeToStream
23+
)
24+
{
25+
_canReadType = canReadType;
26+
_canWriteType = canWriteType;
27+
_readFromStream = readFromStream;
28+
_writeToStream = writeToStream;
29+
}
30+
31+
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
32+
{
33+
return _readFromStream(new ReadFromStreamArgs(type, readStream, content, formatterLogger));
34+
}
35+
36+
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content,
37+
TransportContext transportContext, CancellationToken cancellationToken)
38+
{
39+
return _writeToStream(new WriteToStreamArgs(type, value, writeStream, content, transportContext, cancellationToken));
40+
}
41+
42+
public override bool CanReadType(Type type)
43+
{
44+
return _canReadType(type);
45+
}
46+
47+
public override bool CanWriteType(Type type)
48+
{
49+
return _canWriteType(type);
50+
}
51+
}
52+
}
+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Net;
6+
using System.Net.Http;
7+
using System.Net.Http.Formatting;
8+
using System.Net.Http.Headers;
9+
using System.Text;
10+
using System.Threading;
11+
using System.Threading.Tasks;
12+
13+
namespace ScriptCs.WebApi
14+
{
15+
public class FormatterBuilder
16+
{
17+
private Func<Type, bool> _canReadType = t => true;
18+
private Func<Type, bool> _canWriteType = t => true;
19+
private Func<ReadFromStreamArgs, Task<object>> _readFromStream;
20+
private Func<WriteToStreamArgs, Task> _writeToStream;
21+
private readonly IList<MediaTypeMapping> _mappings;
22+
private readonly IList<MediaTypeHeaderValue> _supportedMediaTypes;
23+
private readonly IList<Encoding> _supportedEncodings;
24+
25+
public FormatterBuilder()
26+
{
27+
_mappings = new List<MediaTypeMapping>();
28+
_supportedMediaTypes = new List<MediaTypeHeaderValue>();
29+
_supportedEncodings = new List<Encoding>();
30+
}
31+
32+
public FormatterBuilder CanReadType(Func<Type, bool> condition)
33+
{
34+
_canReadType = condition;
35+
return this;
36+
}
37+
38+
public FormatterBuilder CanWriteType(Func<Type, bool> condition)
39+
{
40+
_canWriteType = condition;
41+
return this;
42+
}
43+
44+
public FormatterBuilder ReadFromStream(
45+
Func<ReadFromStreamArgs, Task<object>> readFromStream)
46+
{
47+
_readFromStream = readFromStream;
48+
return this;
49+
}
50+
51+
public FormatterBuilder WriteToStream(
52+
Func<WriteToStreamArgs, Task> writeToStream)
53+
{
54+
_writeToStream = writeToStream;
55+
return this;
56+
}
57+
58+
public FormatterBuilder SupportMediaType(MediaTypeHeaderValue mediaType)
59+
{
60+
_supportedMediaTypes.Add(mediaType);
61+
return this;
62+
}
63+
64+
public FormatterBuilder SupportMediaType(string mediaType)
65+
{
66+
_supportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType));
67+
return this;
68+
}
69+
70+
public FormatterBuilder SupportEncoding(Encoding encoding)
71+
{
72+
_supportedEncodings.Add(encoding);
73+
return this;
74+
}
75+
76+
public FormatterBuilder MapQueryString(
77+
string parameterName,
78+
string parameterValue,
79+
MediaTypeHeaderValue mediaType)
80+
{
81+
_mappings.Add(new QueryStringMapping(parameterName, parameterValue, mediaType));
82+
return this;
83+
}
84+
85+
public FormatterBuilder MapQueryString(
86+
string parameterName,
87+
string parameterValue,
88+
string mediaType)
89+
{
90+
_mappings.Add(new QueryStringMapping(parameterName, parameterValue, mediaType));
91+
return this;
92+
}
93+
94+
public FormatterBuilder MapRequestHeader(
95+
string headerName,
96+
string headerValue,
97+
System.StringComparison valueComparison,
98+
bool isValueSubstring,
99+
string mediaType)
100+
{
101+
_mappings.Add(new RequestHeaderMapping(headerName, headerValue, valueComparison, isValueSubstring, mediaType));
102+
return this;
103+
}
104+
105+
public FormatterBuilder MapRequestHeader(
106+
string headerName,
107+
string headerValue,
108+
System.StringComparison valueComparison,
109+
bool isValueSubstring,
110+
MediaTypeHeaderValue mediaType
111+
)
112+
{
113+
_mappings.Add(new RequestHeaderMapping(headerName, headerValue, valueComparison, isValueSubstring, mediaType));
114+
return this;
115+
}
116+
117+
public FormatterBuilder MapUriExtension(
118+
string extension,
119+
string mediaType
120+
)
121+
{
122+
_mappings.Add(new UriPathExtensionMapping(extension, mediaType));
123+
return this;
124+
}
125+
126+
public FormatterBuilder MapUriExtension(
127+
string extension,
128+
MediaTypeHeaderValue mediaType
129+
)
130+
{
131+
_mappings.Add(new UriPathExtensionMapping(extension, mediaType));
132+
return this;
133+
}
134+
135+
public MediaTypeFormatter Build()
136+
{
137+
var formatter = new Formatter(_canReadType, _canWriteType, _readFromStream, _writeToStream);
138+
139+
foreach (var mediaType in _supportedMediaTypes)
140+
{
141+
formatter.SupportedMediaTypes.Add(mediaType);
142+
}
143+
144+
foreach (var mapping in _mappings)
145+
{
146+
formatter.MediaTypeMappings.Add(mapping);
147+
}
148+
149+
foreach (var encoding in _supportedEncodings)
150+
{
151+
formatter.SupportedEncodings.Add(encoding);
152+
}
153+
154+
return formatter;
155+
}
156+
}
157+
}

src/ScriptCs.WebApi/Properties/AssemblyInfo.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414

1515
[assembly: Guid("be92b3c5-a23a-4234-8856-162fb14ec2b1")]
1616

17-
[assembly: AssemblyVersion("0.2.0")]
18-
[assembly: AssemblyFileVersion("0.2.0")]
19-
[assembly: AssemblyInformationalVersion("0.2.0")]
17+
[assembly: AssemblyVersion("1.0.0")]
18+
[assembly: AssemblyFileVersion("1.0.0")]
19+
[assembly: AssemblyInformationalVersion("1.0.0")]

0 commit comments

Comments
 (0)