65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET MVC5 特性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.14/5 (12投票s)

2014年8月8日

CPOL

7分钟阅读

viewsIcon

73932

ASP.NET MVC5 新特性系列

引言

大家好,在这个系列中,我将介绍 ASP.NET MVC5 的几个不同特性。我假设您对 ASP.NET MVC 的早期版本有一定的了解,或者至少了解 MVC 设计模式和 .NET/C#。如果不是,我建议您先学习一些 ASP.NET MVC 的基础教程,这将有助于您更好地理解本文。

首先,让我先带您一览 ASP.NET MVC5 拥有哪些特性。以下提到的技术并不意味着它们是 ASP.NET MVC5 自带的,而是更多地意味着它们与 ASP.NET MVC5 打包在一起,从而鼓励使用它们。例如,Bootstrap 是一个开源的 CSS/JS 库,用于响应式设计。

Bootstrap 用于响应式设计

WebAPI 2 用于创建 RESTful 服务

EF6 用于数据访问

OWIN/Katana – 全新的中间件组件

SignalR – Websocket 通信以及更多功能

在本文中,我将尝试解释和演示 OWIN/Katana 作为中间件 Web 框架。

让我们开始吧

Katana 是一个实现 OWIN(.NET 的开放 Web 接口)的 Web 框架。

OWIN 是一个定义框架和服务器之间通信标准的规范。

OWIN 定义了 .NET Web 服务器和 Web 应用程序之间的标准接口。OWIN 接口的目标是解耦服务器和应用程序,鼓励开发用于 .NET Web 开发的简单模块,并通过成为一个开放标准,刺激 .NET Web 开发工具的开源生态系统。

[定义摘自 http://owin.org/ ]

Katana 是微软对 OWIN 规范的实现。

为了让您有一个初步了解,您可以尝试将其与 ASP.NET 管道中的 Http Modules 的概念进行比较,它实际上是在底层使用的。请注意,这只是一个类比,以帮助您开始理解,但在现实中它远不止于此。

ASP.NET MVC5 示例应用程序中 OWIN 的程序集引用。

让我们来看一个经典的 OWIN/Katana "Hello World" 示例。

  1. 使用 Visual Studio 创建一个控制台应用程序。

2. 安装以下 Nuget 包。

安装这两个 Nuget 包后,您的引用应该如下所示。

HTTP 侦听器 nuget 包需要监听特定端口以接收 HTTP 请求。

3. 我们也创建一个类库项目,以便将 Katana 托管代码单独存放,以实现解耦和重用。确保在此类库项目中也安装相同的 2 个 nuget 包。

4. 现在让我们编写以下代码片段。

类库 托管类 -->

using Owin;
namespace KatanaHosting
{
    public class Hosting
    {
        public void StartHost(IAppBuilder appBuilder)
        {
            appBuilder.Run(
                r => {
                    return r.Response.WriteAsync("Hello World Owin Katana!");
                });
        }
    }
}                                                                                   

控制台应用程序 Program.cs

using KatanaHosting;
using Microsoft.Owin.Hosting;
using System;
using System.Configuration;

namespace OwinHTTPServer
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = ConfigurationManager.AppSettings["url"].ToString();

           //WebApp class's start method takes the host class type as generic type 
           //and accepts the uri as parameter
           //Listen on defined url we have set in app.config. 
           // E.g.     https://:9001                                                                 using (WebApp.Start<Hosting>(url))
            {
                Console.WriteLine("Host Started!");
                Console.ReadLine();
                Console.WriteLine("Host Stopped!");
            }
         }
    }
}                                                                                                                                                                                                  

 

5. 现在让我们尝试运行控制台应用程序。如果您遵循了我上面的代码,很可能会收到以下异常。

查看详细的错误消息,我们看到以下内容。

 

尝试加载应用程序时发生以下错误。

 - 在类 'KatanaHosting.Hosting, KatanaHosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 中未找到 'Configuration' 方法。

 

是的,如果您猜对了,那就说明您猜对了 J。

我们需要将 Hosting 类的名称命名为 Configuration(IAppBuilder appBuilder)。是的,ASP.NET MVC 现在有很多约定。

6. 现在让我们再次尝试运行控制台应用程序,我们的 Web 服务器已启动并正在运行。

 

7. 让我们通过打开浏览器窗口并输入我们在配置文件中给出的 URL(在我的例子中是 https://:9001)来测试我们的 Katana Web 服务器,然后在浏览器中看到 Web 服务器的响应。 

 

Microsoft.Owin.Diagnostics

现在让我们尝试探索 OWIN/Katana 的一些功能。

在我们的 Hosting 类库中安装另一个 nuget 包 Microsoft.Owin.Diagnostics。

现在让我们修改 Hosting 类的 Configuration 方法,使其显示一个欢迎页面而不是 "Hello World" 响应。

public class Hosting
{
        public void Configuration(IAppBuilder appBuilder)
        {
            appBuilder.UseWelcomePage();
            
        }
}
     

现在,当我们尝试浏览 https://:9001 时,我们会看到一个漂亮的欢迎页面。

AppFunc – 应用程序函数

AppFunc 函数指定组件之间如何交互并处理 HTTP 请求。

AppFunc 采用委托签名 Func<IDictionary<string, object>, Task>,这意味着它接受一个字典并返回一个任务。该字典主要包含从服务器接收到的请求和服务器返回的响应等所有内容。我们可以将该字典与 ASP.NET 中的 HttpContext 对象进行比较,该对象包含 HTTP 请求处理的详细信息。Func 返回一个任务,因为我们这里讨论的是异步请求/响应,类似于 MVC4 中的 Async/Await。因此,这是一个非阻塞的请求/响应系统,一个请求不必等待前一个请求完成。

不用担心这里的细节,我们很快就会看到一个示例。

让我们用一些自定义代码重写上面的欢迎页面示例,这些代码使用 Uses<> 函数来调用我们的代码片段并返回 "Hello World" 字符串。

我们在这里编写一个名为 "AppFuncServer" 的新类。

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace KatanaHosting
{
    public class AppFuncServer
    {
        Func<IDictionary<string, object>, Task>_next;
        
        //Constructor to show next component call.
        public AppFuncServer(Func<IDictionary<string, object>, Task> next)
        {
            _next = next;
        }                                                                                                                                                                                                                                                                                                     public async Task<string> Invoke(IDictionary<string, object> env)
        {
            //Await just to show E.g of asynchronous behaviour.
            await _next(env);
            
          //We have the env dictionary where we specify owin.ResponseBody and cast to Stream type.
            var response = env["owin.ResponseBody"] as Stream;
            using(var writer = new StreamWriter(response))
            {
                return writer.WriteAsync("Hello World").ToString();
            }
        }
    }
}

Hosting 类

namespace KatanaHosting
{
    public class Hosting
    {
        public void Configuration(IAppBuilder appBuilder)
        {
//Instead of Welcome page, we will use the Use<> function and pass type of our 
//AppFuncServer class.
            appBuilder.Use<AppFuncServer>();
        }
    }
}

在浏览器窗口中运行 https://:9001/,您将能够再次看到 "Hello World",并带有新的自定义代码。

Katana/OWIN 作为中间件

我告诉过您 OWIN 实际上是一个中间件吗?为什么?

因为它位于请求管道的中间,并且能够将请求转发给下一个组件。让我们通过尝试在服务器控制台应用程序中在响应之前写出主机头值来了解它是如何充当中间件的。

扩展上面的示例,将主机头值输出到控制台应用程序。现在您相信它能像中间件一样工作了吗?;)

Hosting.cs 类

using Owin;
using System;                                                                                                                                                                                       namespace KatanaHosting
{
    public class Hosting
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            // Use method takes a lambda expression and the 1st parameter has access to several properties
            // like the Request object.
            appBuilder.Use(async (env, next) => {
                Console.WriteLine(env.Request.Host.Value);
                await next();
            });                                                                                                                                                                                                                                                                                                                                                                                                   appBuilder.Use<AppFuncServer>();
        }
    }
}                                                                                                                                                                                                                                                                                                                                                                                                                                                              

您可能在想,OWIN 和 Katana 的 "Hello World" 示例很好,但我的应用程序在哪里,它最终将负责管理业务逻辑/规则/数据访问等?是的,所以您不必再等待了。让我们通过一个使用 WebAPI 的示例,它也将是自托管的。

WebAPI

  1. 在控制台应用程序中安装 Microsoft.AspNet.WebApi.OwinSelfHost nuget 包。它有一些依赖包将自动安装。
  2. 让我们添加一个名为 RouteConfig.cs 的类文件。是的,我试图使用与 ASP.NET WebAPI 相同的模式。
namespace KatanaHosting
{
    public class RouteConfig
    {
        public static void RegisterRoutes(IAppBuilder appBuilder, ref HttpConfiguration config)
        {
            //Same old route as the MVC4 webapi
            config.Routes.MapHttpRoute(
                    "DefaultApi",
                    "api/{controller}/{id}",
                    new { id = RouteParameter.Optional}
                );
        }
    }
}
namespace KatanaHosting
{
    public class Hosting
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            // Use method takes a lambda expression and the 1st parameter has access 
//to several properties
            // like the Request object.                                                                                                                                                                          appBuilder.Use(async (env, next) => {
                Console.WriteLine(env.Request.Host.Value);
                await next();
            });                                                                                                                                                                                                 //A HttpConfiguration object is needed to set the route.
            var config = new HttpConfiguration();
            RouteConfig.RegisterRoutes(appBuilder, ref config);
            appBuilder.UseWebApi(config);
            appBuilder.Use<AppFuncServer>();                                                                                                                                                                 }
    }
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

3. 添加一个 HomeController 类,它继承自 ApiController,使其成为一个 WebAPI 控制器,并添加一个简单的 Get 方法来返回一个字符串。

namespace KatanaHosting
{
    public class HomeController : ApiController
    {
        public string GetHome()
        {
            return "Hello World from Web API";
        }
    }
}

 

就是这样。运行控制台应用程序以启动服务器,然后浏览 https://:9001/api/Home,我们将看到 WebAPI 愉快地将 XML 响应返回给客户端。

Katana 和 IIS

1. 将 Nuget 包安装到我们的类库 KatanaHosting 中。

此包将执行必要的操作,以在 Katana 和 IIS 管道之间建立连接并托管 Katana 中间件。它基本上是通过其自己的 HttpModules 和 HttpHandlers 来实现的。

2. 更改 KatanaHosting 库项目的输出路径到 bin 目录,因为现在我们正在尝试在 IIS 下托管此项目。

3. 为我们的 KatanaHosting 项目创建一个 Web.config 文件,因为我们现在需要在 IIS 下进行托管。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="owin:appStartup" value="KatanaHosting.Hosting" />
  </appSettings>
 <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

 

 

4. 在 IIS 中创建一个网站,并将物理目录指向 KatanaHosting 项目。

 

5. 尝试在托管端口 https://:8080 上浏览该站点,以及 api URL https://:8080/api/Home,您应该能够像以前一样浏览 "Hello World" 示例,但现在托管在 IIS 中。顺便说一句,要测试之前将请求主机头值写入控制台的 Katana 中间件组件,您可以尝试将其写入文件。

 

现在让我们尝试查看使用 Katana/OWIN 的默认 ASP.NET MVC5 应用程序。

  1. 让我们在 Visual Studio 2013 或 Visual Studio 2012(需要 http://www.microsoft.com/en-us/download/details.aspx?id=41532 )中创建一个新的 ASP.NET MVC5 应用程序。
  2. 如果您打开引用,您可以看到 OWIN dll 已存在。
  3. 您还可以在网站的根目录中看到一个启动文件,其中包含以下代码。
using Microsoft.Owin;
using Owin;                                                                                        
[assembly: OwinStartupAttribute(typeof(Sample_MVC5.Startup))]

namespace Sample_MVC5
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

 

如果您查看 ConfigureAuth() 方法,身份验证相关内容就在那里完成。

此外,命名空间上方的程序集属性定义了启动类,在我们的 KatanaHosting 类库示例中,我们是在 Web.config 中完成的,所以这是配置启动类的另一种方式。

关注点

在本文中,我们学习了 Katana 如何使用 OWIN 规范作为中间件 Web 框架,以及如何在不同类型的应用程序中使用它,例如我们一次在控制台应用程序中使用,一次在网站中使用。 

在未来的文章中,我们将探讨 Katana/OWIN 的更多用途以及 ASP.NET MVC5 的其他特性。

 

© . All rights reserved.