如果我们想对外发布RESTful API,可以基于ASP.NET来构建Restful APIs,但需要部署IIS吗?答案是不必。你可以把它托管到一个Windows Service。具体如何把WEB API自托管到Windows Service可以参考这一文章:Self-Host a Web API (HttpSelfHostServer) (C#). 基本上照着一步步做就行了。例子里是基于Windows Console Application,同样可以Self-Host到Windows Service.
问题在于如何把Controllers从Windows Service分离?可以使用autoFac,本文具体从这展开。
使用autoFac分离Controllers
autoFac是一个.NET IoC容器框架,这里我们用来分离Controllers,也就是说,我们把MVC的控制器Controllers放到独立的一个工程(Project),然后在Windows Service里面自托管(Self-Host)RESTful APIs。部署的时候只要部署windows service即可,不需要IIS,外部一样可以调用我们的RESTful APIs. 需要做的就是: 1. 引用autoFac 2. 注册Controllers 3. 设置DependencyResolver。好,我们新建一个project,类型是类库dll。添加引用:System.Web.Http;添加一个Controller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
using
System;
using
System.Net;
using
System.Net.Http;
using
System.Web.Http;
using
Newtonsoft.Json;
namespace
myCompany
{ public
class
GroupController : ApiController, IGroupController
{
public
HttpResponseMessage Update(HttpRequestMessage request)
{
Model model = null ;
var
body = "" ;
var
valid = true ;
var
result = new
response { success = true , message = ""
};
HttpResponseMessage response;
try
{
body = request.Content.ReadAsStringAsync().Result;
/*
* According to the content type (text / json / xml), deserialize the request body
*/
model = Deserialize(body,
ModelUtility.GetMediaType(request.Content.Headers.ContentType.ToString()));
if
(model == null )
valid = false ;
}
catch
(Exception e)
{
valid = false ;
}
if
(!valid)
{
response = BuildFailureResponse( string .Format(
"Failure during parsing the request [{0}]" , body));
}
else
{
response = Request.CreateResponse<response>(HttpStatusCode.OK, result);
}
return
response;
}
private
static
Model Deserialize( string
data, MediaTypes type)
{
switch
(type)
{
case
MediaTypes.HTML:
break ;
case
MediaTypes.JSON:
return
JsonConvert.DeserializeObject<Model>(data);
case
MediaTypes.TEXT:
return
new
Model
{
name = ModelUtility.ParseText(data, "name" ),
status = ModelUtility.ParseText(data, "status" )
};
case
MediaTypes.XML:
return
Utility.XmlSerilizer.Deserialize<Model>(data);
case
MediaTypes.UNKNOWN:
break ;
default :
break ;
}
return
null ;
}
private
HttpResponseMessage BuildFailureResponse( string
message)
{
var
result = new
response { success = false , message = message };
return
Request.CreateResponse<response>(HttpStatusCode.BadRequest, result);
}
}
} |
上面那个控制器可以处理RESTful API涉及group的请求。具体下面再谈。
回到我们已经创建Self-Host的Windows Service项目,里面添加引用Autofac.dll和Autofac.Integration.WebApi.dll。此外,可能还需要一些引用,我这里的列表如下:
然后在Windows Service项目里面添加一个类,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using
System.Reflection;
using
System.Web.Http;
using
Autofac;
using
Autofac.Integration.WebApi;
namespace
myCompany
{ public
class
AutofacWebAPI
{
public
static
void
Initialize(HttpConfiguration config)
{
config.DependencyResolver = new
AutofacWebApiDependencyResolver(
RegisterServices( new
ContainerBuilder())
);
}
private
static
IContainer RegisterServices(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.RegisterType<GroupController>().As<IGroupController>();
return
builder.Build();
}
}
} |
主要就是用来aufoFac初始化和注册类型。然后在Windows service里面调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public
partial
class
Service : ServiceBase
{ private
HttpSelfHostServer _server;
private
readonly
HttpSelfHostConfiguration _config;
public
Service()
{
InitializeComponent();
_config = new
HttpSelfHostConfiguration(_serviceAddress);
_config.Routes.MapHttpRoute( "DefaultApi" ,
"notifications/{controller}/{id}" ,
new
{ id = RouteParameter.Optional });
}
protected
override
void
OnStart( string [] args)
{
/* Start self-host Web API */
AutofacWebAPI.Initialize(GlobalConfiguration.Configuration);
_server = new
HttpSelfHostServer(_config);
_server.OpenAsync();
}
} |
就这么简单。此外,你还可以用其他的DependencyResolver方式,具体参考autoFac官方文档:https://code.google.com/p/autofac/wiki/WebApiIntegration
最后如何测试呢?
HTTP POST http://localhost:8080/notifications/group/update
post body (text/plain): name=abc&status=CANCELLED
post body
(application/json): "{\"name\":\"abc\",\"status\":\"CANCELLED\"}";
post
body (application/xml):
@"<myc:root
xmlns:myc=""http://api.abc.com/Platform/1.0"">
<myc:name>abc</myc:name>
<myc:status>CANCELLED</myc:status>
</myc:root>";
看不懂的,可看代码。支持text/json/xml多种参数格式。RESTful API测试可以用Chrome插件:Postman REST Client。