在 Nowin 下运行 ASP.NET 5 Beta 2
在 Nowin 下运行 ASP.NET 5 Beta 2
ASP.NET Mvc vNext 改名为 ASP.NET 5 , 看来距离正式发布已经不远了, 在发布之初就号称可以跨平台运行, 在发布的早期 alpha 版本中, 做个一次在 mono 下尝试 ASP.NET vNext的试验, 虽然最终以失败告终, 但是在试验的过程中还是还是收获良多, 对 OWIN 有了更深一步的认识, 也熟悉了 OWIN 的第三方实现 Nowin 。
现在最新发布的 ASP.NET 5 版本为 Beta 2, 不仅功能更加完善, 第三方资料也多了很多, 不过完全依靠微软提供的资源还不能在非 Windows 平台运行, ASP.NET 5 可以在 OWIN 环境下运行, 而 OWIN 是开源开放的, 也有第三方实现可以在非 Windows 平台下基于 Mono 运行, 因此借助第三方的 OWIN 实现在非 Windows 平台下基于 Mono 运行 ASP.NET 5 也是完全可以的。
使用 Nowin 搭建 ASP.NET 5 服务器
用 VS 2015 CTP5 创建一个 ASP.NET 5 类库项目, 命名为 Nowin.vNext 如下图所示:
打开 project.json 文件, 添加下面三个依赖项:
{
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-beta2",
"Microsoft.AspNet.Owin": "1.0.0-beta2",
"Nowin": "0.13.6.0"
}
}
由于使用 Nowin
这个传统类库, 不适用于 aspnetcore50
, 因此要从 frameworks
下删除, 只保留 aspnet50
, 最后的 project.json 如下所示:
{
"version": "1.0.0-*",
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-beta2",
"Microsoft.AspNet.Owin": "1.0.0-beta2",
"Nowin": "0.13.6.0"
},
"frameworks" : {
"aspnet50" : {
"dependencies": {
}
}
}
}
要搭建 ASP.NET 5 服务器, 至少需要实现两个接口 IServerInformation
和 IServerFactory
, 对这两个接口的实现分别如下:
实现 IServerInformation
IServerInformation 接口是需要实现者提供服务器的一些信息, 定义如下:
namespace Microsoft.AspNet.Builder {
public interface IServerInformation {
string Name { get; }
}
}
从接口的定义来看, 只需要提供个服务器名称即可, 当然用 Nowin 实现这个接口时, 包含了 Nowin.ServerBuilder
实例成员, 可以提供额外的关于 Nowin 的一些信息, 实现代码如下:
using System;
using Microsoft.AspNet.Builder;
using Nowin;
namespace Nowin.vNext {
public class NowinServerInformation : IServerInformation {
public ServerBuilder Builder { get; }
string IServerInformation.Name => "Nowin";
public NowinServerInformation(ServerBuilder builder) {
Builder = builder;
}
}
}
实现 IServerFactory
上面的 NowinServerInformation
比较简单, 只是简单的提供服务器信息, 接下来要实现的 IServerFactory
就是关键了, IServerFactory
的定义如下:
namespace Microsoft.AspNet.Hosting.Server {
[AssemblyNeutral]
public interface IServerFactory {
IServerInformation Initialize(IConfiguration configuration);
IDisposable Start(
IServerInformation serverInformation,
Func<object, Task> application
);
}
}
ASP.NET 5 既然是基于 OWIN 运行的, 自然少不了 OWIN 的标志性函数 Func<IDictionary<string, object>, Task>
了, 在我们的实现中, 自然也必须用到这个函数, 我们先来定义这样一个 HandleRequest 函数, 作为 OWIN 的处理函数:
private Task HandleRequest(IDictionary<string, object> env) {
}
第一步, 将当前 ASP.NET 5 应用适配成一个标准的 OWIN 应用, 代码如下:
IServerInformation IServerFactory.Initialize(IConfiguration configuration) {
// adapt aspnet to owin app Func<IDictionary<string, object>, Task>;
var owinApp = OwinWebSocketAcceptAdapter.AdaptWebSockets(HandleRequest);
}
第二步, 从 configuration 参数中提取必要的服务器信息 (服务器名称、要监听的地址), 并返回 IServerInformation
的实例, 在上面的 Inisitlize
方法中继续添加下面的代码:
// Get server info, write to console.
var server = configuration.Get("server");
var serverUrls = configuration.Get("server.urls");
Console.WriteLine("Owin server is: {0}, listening at {1}", server, serverUrls);
// parse ip address and port.
var uri = new Uri(serverUrls, UriKind.Absolute);
IPAddress ip;
if (!IPAddress.TryParse(uri.Host, out ip)) {
if (uri.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase)) {
ip = IPAddress.Parse("127.0.0.1");
}
else {
ip = IPAddress.Any;
}
}
var port = uri.Port;
// build nowin server;
var builder = ServerBuilder.New()
.SetAddress(ip)
.SetPort(port)
.SetOwinApp(owinApp);
var serverInfo = new NowinServerInformation(builder);
return serverInfo;
第三步继续来实现 IServerFactory.Start
方法, 这个方法有两个参数:
-
IServerInformation
就是在 initialize 方法中返回的 NowinServerInformation 实例; -
Func<object, Task>
是 ASP.NET 5 运行时提供给 OWIN 环境调用的处理函数, 也就是说, 在 OWIN 环境下运行 ASP.NET 5 就是调用这个函数。
实现代码如下:
IDisposable IServerFactory.Start(
IServerInformation serverInformation,
Func<object, Task> application
) {
// get server info,
var info = (NowinServerInformation)serverInformation;
// save the application callback
this.callback = application;
// build and start nowin server.
var server = info.Builder.Build();
server.Start();
return server;
}
private Func<object, Task> callback;
private Task HandleRequest(IDictionary<string, object> env) {
// just call the application callback ASP.NET 5 provided.
return callback(new OwinFeatureCollection(env));
}
到现在为止, 基于 Nowin 的 ASP.NET 5 OWIN 服务器已经建好了, 接下来添加一个 ASP.NET 5 应用来测试一下。
运行测试程序
新建一个 ASP.NET 5 空 Web 项目, 命名为 MvcEmptyApp , 如下图所示:
打开 project.json 文件, 添加如下的依赖项:
{
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-beta2",
"Microsoft.AspNet.Mvc": "6.0.0-beta2",
"Microsoft.AspNet.Server.IIS": "1.0.0-beta2",
"Microsoft.AspNet.Server.WebListener": "1.0.0-beta2",
"Microsoft.Framework.DependencyInjection": "1.0.0-beta2",
"Nowin.vNext": ""
}
}
同样, 需要将 aspnetcore50
从 frameworks
节点下删除, 并添加一个名称为 nowin
的启动命令, 如下所示:
{
"commands": {
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls https://localhost:8080",
"nowin": "Microsoft.AspNet.Hosting --server Nowin.vNext --server.urls https://localhost:8080"
},
"frameworks" : {
"aspnet50" : { }
}
}
将 MvcEmptyApp 设置为启动项目, 并设置 Nowin
为启动命令, 如下图所示:
编辑 Startup.cs
, 代码如下所示:
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.Hosting;
namespace MvcApp {
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
app.UseMvc(routeBuilder => {
routeBuilder.MapRoute(
name: "Default",
template: "{controller=Home}/{action=Index}/{id?}"
);
});
}
}
}
再添加一个 HomeController , 代码如下:
using Microsoft.AspNet.Mvc;
using System;
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace MvcApp.Controllers {
public class HomeController : Controller {
// GET: /<controller>/
public IActionResult Index() {
return Content("Hello, ASP.NET Mvc under " + Environment.OSVersion.ToString());
}
}
}
接下来可以 F5
直接在 VS 下运行, 也可以在命令行窗口直接输入 k nowin
命令来运行, 在 Windows 下运行如下图所示:
Mac 系统下运行
本文所有源代码: https://github.com/beginor/mvc-vnext
- C/C++中对链表操作的理解&&实例分析
- COGS 2482. Franky的胡子【二分,高精度】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战02】理解gym的建模思想
- Kruscal(最小生成树)算法模版
- BZOJ 3680: 吊打XXX【模拟退火算法裸题学习,爬山算法学习】
- 区块链概况:什么是比特币
- 简化版桶排序操作模版
- BZOJ 3670: [Noi2014]动物园【KMP变形 】
- 【延迟注入】A5站长网某站存在SQL注入漏洞
- hihoCoder #1498 : Diligent Robots【数学】
- Codeforces Round #336 (Div. 2)【A.思维,暴力,B.字符串,暴搜,前缀和,C.暴力,D,区间dp,E,字符串,数学】
- 【防护】如何阻止SELECT * 语句
- COGS 862. 二进制数01串【dp+经典二分+字符串】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战03】编写通用的格子世界环境类
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- webpack实战——预处理器(loader)【上篇】
- Mac安装git,brew出现的问题
- dotnet OpenXML 简单聊聊 PPT 文本解析
- R语言作图——Ridgeline plot(山脊图)
- dotnet OpenXML 的 spcPct 和 spcPts 表示距离的不同
- 深入剖析.NETCORE中CORS(跨站资源共享)
- 网络安全实验室平台(基础关)
- Unity 基于excel2json批处理读取Excel表并反序列化
- dotnet OpenXML 文本 Text Line Break 的作用
- CVE-2020-1362 漏洞分析
- wpa_supplicant 框架
- 【LeetCode每日一题】25. Reverse Nodes in k-Group
- upload-labs第一关
- upload-labs第2~8关
- dotnet OpenXML 文本 ParagraphProperties 的属性作用