第 7 章 开发 ASP.NET Core Web 应用

ASP.NET Core 基础

在本章,我们将从一个命令行应用开始,并且在不借助任何模板,脚手架和向导的情况下,最终得到一个功能完整的 Web 应用

GitHub链接:https://github.com/microservices-aspnetcore/hello-world

运行 dotnet new console 命令之后,我们首先得到一个 Program.cs 文件,修改该文件并添加配置支持

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration; namespace StatlerWaldorfCorp.HelloWorld
{
public class Program
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.Build(); var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.UseConfiguration(config)
.Build(); host.Run();
}
}
}

之后添加一个 Startup 类,用于配置默认的中间件,它对所有 HTTP 请求都返回 "Hello World" 响应

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http; namespace StatlerWaldorfCorp.HelloWorld {
public class Startup
{
public Startup(IHostingEnvironment env)
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello, world!\n");
});
}
}
}

添加 NuGet 包作为项目的依赖,并直接在项目文件开头处声明要使用的 Web SDK

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">

  <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1"/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1"/>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1"/>
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="1.1.1"/>
</ItemGroup> </Project>

添加 ASP.NET MVC 中间件

GitHub链接:https://github.com/microservices-aspnetcore/webapp

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration; namespace StatlerWaldorfCorp.WebApp
{
public class Startup
{
public Startup(IHostingEnvironment env)
{ } public IConfiguration Configuration { get; set; } public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseMvc(routes =>
{
routes.MapRoute("default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

为了让它生效,我们还需要添加 NuGet 包依赖:Microsoft.AspNetCore.Mvc

添加控制器

控制器专门负责:

  • (1)接收来自 HTTP 请求的输入
  • (2)将输入转交给与 HTTP 通信、JSON解析无关的服务类处理
  • (3)返回合适的响应代码及正文
using Microsoft.AspNetCore.Mvc;
namespace StatlerWaldorfCorp.WebApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return "Hello World";
}
}
}

只要向文件中加入上面的内容,此前创建的路由就能自动检测到这个控制器并让它生效

添加模型

我们创建了一个用于表示股票报价的简单模型

namespace StatlerWaldorfCorp.WebApp.Models
{
public class StockQuote
{
public string Symbol { get; set; }
public int Price { get; set; }
}
}

添加视图

<html>
<head>
<title>Hello world</title>
</head>
<body>
<h1>Hello World</h1>
<div>
<h2>Stock Quote</h2>
<div>
Symbol: @Model.Symbol<br/>
Price: $@Model.Price<br/>
</div>
</div>
</body>
</html>

现在,我们可用修改 HomeController,不再返回示例文本,而是呈现视图

using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using StatlerWaldorfCorp.WebApp.Models; namespace StatlerWaldorfCorp.WebApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
var model = new StockQuote { Symbol = "HLLO", Price = 3200 }; return View(model);
}
}
}

如果现在运行应用,很可能会收到 HTTP 500 响应

由于我们开发的是 Web 应用,因而一定希望能查看所有发生错误的堆栈信息

可用向 Startup 类的 Configure 方法中加入一行调用 UseDeveloperExceptionPage 的代码,实现这一需求

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration; namespace StatlerWaldorfCorp.WebApp
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddEnvironmentVariables(); Configuration = builder.Build();
} public IConfiguration Configuration { get; set; } public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
loggerFactory.AddDebug(); app.UseDeveloperExceptionPage();
app.UseMvc(routes =>
{
routes.MapRoute("default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseStaticFiles();
}
}
}

有了新的 Startup 类,我们应该能够通过 dotnet restore 以及 dotnet run 启动应用

从 JavaScript 中调用 REST API

首先,我们通过添加新的控制器来创建 API 端点

using Microsoft.AspNetCore.Mvc;
using StatlerWaldorfCorp.WebApp.Models; namespace StatlerWaldorfCorp.WebApp.Controllers
{
[Route("api/test")]
public class ApiController : Controller
{
[HttpGet]
public IActionResult GetTest()
{
return this.Ok(new StockQuote { Symbol = "API", Price = 9999 });
}
}
}

如果现在再运行应用,可用打开浏览器并访问 http://localhost:5000/api/test,应该能看到一个 JSON 响应

{
"symbol" : "API",
"price" : 9999
}

有了可供消费的 API 后,现在来修改我们唯一的视图,让它调用 JavaScript 来消费这个 API

<html>
<head>
<title>Hello world</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="/Scripts/hello.js"></script>
</head>
<body>
<h1>Hello World</h1>
<div>
<h2>Stock Quote</h2>
<div>
Symbol: @Model.Symbol<br/>
Price: $@Model.Price<br/>
</div>
</div>
<br/>
<div>
<p class="quote-symbol">The Symbol is </p>
<p class="quote-price">The price is $</p>
</div>
</body>
</html>

注意,这里决定引入一个 jQuery,以及一个新脚本 hello.js

我们按照约定,把它添加到名为 wwwroot 的新目录 wwwroot/Scripts/hello.js

$(document).ready(function () {
$.ajax({
url: "/api/test"
}).then(function (data) {
$('.quote-symbol').append(data.symbol);
$('.quote-price').append(data.price);
});
});

这些 jQuery 代码非常直观,它们向 API 端点发送 Ajax 请求,返回的对象会包含 symbol 和 price 属性,它们将被附加到新添加的段落标签之中

开发云原生 Web 应用

  • (1)API 优先
  • (2)配置
  • (3)日志
  • (4)会话状态
  • (5)数据保护
  • (6)后端服务
  • (7)环境均等
  • (8)端口绑定
  • (9)遥测
  • (10)身份验证和授权
会话状态

云原生 Web 应用基本上不可能再使用基于内存的会话状态了,而必须使用进程外的提供程序

数据保户

如果涉及数据保护,”进程外存储“的思路同样适用于密钥存储

我们要使用一种现成的密钥保管库,可以是基于云的密钥保管库,也可以是基于 Redis 或其他数据库制作的定制解决方案

端口绑定

不管是使用 docker compose,部署到 Kubernetes,还是使用 AWS、Azure 或者 GCP,应用要想在云环境中运行良好,就要能接受为它预设的任何端口号

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

《ASP.NET Core 微服务实战》-- 读书笔记(第7章)的更多相关文章

  1. JavaScript DOM编程艺术读书笔记(三)

    第七章 动态创建标记 在web浏览器中往文档添加标记,先回顾下过去使用的技术: <body> <script type="text/javascript"> ...

  2. JavaScript DOM编程艺术读书笔记(二)

    第五章 最佳实践 平稳退化(graceful degradation):如果正确使用了JavaScript脚本,可以让访问者在他们的浏览器不支持JavaScript的情况下仍能顺利地浏览你网站.虽然某 ...

  3. JavaScript DOM编程艺术读书笔记(一)

    第一章,第二章 DOM:是一套对文档的内容进行抽象和概念化的方法. W3C中的定义:一个与系统平台和编程语言无关的接口,程序和脚本可以通过这个接口动态的访问和修改文档的内容,结构和样式. DHTML( ...

  4. JavaScript DOM编程艺术 - 读书笔记1-3章

    1.JavaScript语法 准备工作 一个普通的文本编辑器,一个Web浏览器. JavaScript代码必须通过Html文档才能执行,第一种方式是将JavaScript代码放到文档<head& ...

  5. JavaScript DOM编程艺术 读书笔记

    2. JavaScript语法 2.1 注释      HTML允许使用"<!--"注释跨越多个行,但JavaScript要求这种注释的每行都必须在开头加上"< ...

  6. JavaScript DOM编程艺术读书笔记(四)

    第十章 实现动画效果 var repeat = "moveElement('"+elementID+"',"+final_x+","+fin ...

  7. JavaScript DOM编程艺术-学习笔记(第二章)

    1.好习惯从末尾加分号:开始 2.js区分大小写 3.程序界万能的命名法则:①不以,数字开头的数字.字母.下划线.美元符号 ②提倡以下划线命名法来命名变量,以驼峰命名法来命名函数.但是到了公司往往会身 ...

  8. 《javascript dom编程艺术》笔记(一)——优雅降级、向后兼容、多个函数绑定onload函数

    刚刚开始自学前端,如果不对请指正:欢迎各位技术大牛指点. 开始学习<javascript dom编程艺术>,整理一下学习到的知识.今天刚刚看到第六章,记下get到的几个知识点. 优雅降级 ...

  9. JavaScript DOM编程艺术学习笔记(一)

    嗯,经过了一周的时间,今天终于将<JavaScript DOM编程艺术(第2版)>这本书看完了,感觉受益匪浅,我和作者及出版社等等都不认识,无意为他们做广告,不过本书确实值得一看,也值得推 ...

  10. JavaScript DOM编程艺术-学习笔记

    发现基础不是很好,补习一下.37买了2本书(dom编程和高级程序设计). 以前读书总是自己勾勾画画,有点没意思.现在写下来,说不定会成为传世经典.哈哈...........随便扯扯淡. 第一天(201 ...

随机推荐

  1. freeswitch的3XX重定向

    概述 sip协议标准RFC3261中,对3XX重定向有明确的定义. freeswitch中如何使用3XX redirect的特性,如何落地,应用场景有哪些? 环境 centos:CentOS  rel ...

  2. 一文搞清楚Java中的包、类、接口

    写在开头 包.类.接口.方法.变量.参数.代码块,这些都是构成Java程序的核心部分,即便最简单的一段代码里都至少要包含里面的三四个内容,这两天花点时间梳理了一下,理解又深刻了几分. Java中的包 ...

  3. Redis 缓存常见问题

    本文为博主原创,未经允许不得转载: 目录: 1. 缓存穿透 1.1 出现原因 1.2 解决方案 1.3 布隆过滤器 2. 缓存雪崩 3. 缓存失效(缓存击穿,热点缓存) 1. 缓存穿透: 缓存穿透是指 ...

  4. 【SHELL】跨行内容查找、替换、删除

    跨行内容查找.替换.删除 sed '/START-TAG/{:a;N;/END-TAG/!ba};/ID: 222/d' data.txt /START-TAG/ { # Match 'START-T ...

  5. 【TouchGFX】使用CubeMX创建touchgfx项目 -- 初始篇

    1.系统构成,黑色块表示组件非必须 2.环境准备 CubeMX:6.0.1 touchgfx:4.15.0 rt-thread:2020-8-14 commit Keil:5.30 board:stm ...

  6. [java] - JavaBeans 获取 session

    RegServlet // 保存到 session request.getSession().setAttribute("user", user); userinfo.jsp // ...

  7. springboot封装统一返回

    springboot返回统一的标准格式 定义注解 package com.yaoling.annotation; import java.lang.annotation.*; @Target({Ele ...

  8. SpringBoot开启动态定时任务并手动、自动关闭

    场景需求:在执行某个方法的两小时之后进行某个操作 涉及:定时任务.哈希表 需要注意:业务逻辑层是单一实例的,所以在定时任务类内操作业务逻辑层的某个属性和在业务逻辑层内操作的都是同一个. 疑问:Thre ...

  9. [转帖]为什么不推荐使用/etc/fstab

    https://www.jianshu.com/p/af49a5d0553f 对于工作中使用服务器的公司来讲,每到节假日来临时,总免不了对服务器进行下电.而收假回来的早上,则会有一个早上的时间会花费在 ...

  10. [转帖]Guanaco, Llama, Vicuña, Alpaca该怎么区别

    https://zhuanlan.zhihu.com/p/106262896 在智利和秘鲁高原区经常会遇到的一种动物让人十分挠头,学术点称呼就是骆驼科其中一个族群--羊驼属和骆马属.头疼在于,分不清楚 ...