ASP.NET Core 3在React SPA方面有什么新内容?

134 阅读3分钟

ASP.NET Core 3最近已经发布了。React SPA可以利用的新功能有哪些?让我们来了解一下 ...

MVC服务注册

Startup 类的ConfigureServices 方法中,有一些新的扩展方法用于添加MVC相关的服务。AddMvc 将继续照常工作,添加所有MVC相关的服务。然而,我们现在有AddControllersAddControllersWithViewsAddRazorPages ,它们为更多的特定场景添加服务。

  • AddControllers.当应用程序是纯粹的网络API,不需要任何服务器端的视图或Razor页面时,可以使用这个方法:
public void ConfigureServices(IServiceCollection services)
{
  services.AddControllers();
}
  • AddControllersWithViews.当应用程序是一个网络API,有一些服务器端的视图时,可以使用这个服务。
  • AddRazorPages.当应用程序使用Razor页面时可以使用这个。请注意,为了获得Web API的功能,还需要调用AddControllersAddControllersWithViews

端点路由

端点路由将匹配哪个端点将执行的过程与该端点的实际运行分开。 这使得路由信息可以在HTTP请求处理管道中更早地被使用。

app.UseMvc 为了在ASP.NET Core 3.0中为我们所有的API控制器创建端点,我们用app.UseEndpoints

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  ...

  app.UseEndpoints(endpoints =>
  {
    endpoints.MapControllers();
  });
}

关于端点路由的更多信息,请看Areg Sarkissian的这篇精彩文章

内置JSON支持

ASP.NET Core不再依赖Json.NET来序列化和反序列化JSON。在System.Text.Json 名称空间中添加了一个JsonSerializer 类,其中包含SerializeDeserialize 方法。在内部,ASP.NET Core在模型绑定过程中使用这个类。如果我们的网络API需要调用其他网络API,我们可以使用它来反序列化响应:

var jsonContent = await response.Content.ReadAsStringAsync();
var user = JsonSerializer.Deserialize<User>(jsonContent, new JsonSerializerOptions
{
  PropertyNameCaseInsensitive = true
});

C# 8

C#有很多有用的功能,包括可归零的引用类型。我们需要在我们的项目文件中启用可归零引用类型,如下所示:

<PropertyGroup>
  ...
  <LangVersion>8.0</LangVersion>
  <Nullable>enable</Nullable>
</PropertyGroup>

参考类型在默认情况下是不能归零的。然后,当我们的代码中可能出现空引用异常时,Visual Studio会警告我们。

nullable reference types

开关表达式也很好。这些是映射代码的理想选择,为我们节省了一些宝贵的击键次数:

public static string GetLevel(int level) =>
  level switch
  {
    1 => "low",
    2 => "medium",
    3 => "high",
    _ => throw new ArgumentException("invalid level"),
  };

查看文档以了解C# 8的其他功能。

SPA模板可以包括认证和授权

当使用SPA模板创建一个新项目时,现在可以选择包括认证:

spa with auth 1024x732

这个例子的web API控制器使用Authorize 属性实现了一个受保护的端点:

[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    ...
}

还请注意,这个例子的web API控制器现在继承了ControllerBase ,并使用ApiController 属性进行了装饰。使用ControllerBase ,意味着该类不包含处理服务器端视图的不必要的东西。ApiController 属性意味着无效的请求模型将返回HTTP状态代码400(坏请求),而我们不需要在动作方法中做任何工作。

React客户端使用一个AuthorizeService 类来封装与身份服务器的交互。这是对oidc-client npm包的一个很好的包装。

React客户端还包含AuthorizeRoute 组件,这样可以轻松实现授权路径:

<Layout>
  <Route exact path='/' component={Home} />
  <Route path='/counter' component={Counter} />
  <AuthorizeRoute path='/fetch-data' component={FetchData} />
  <Route path={ApplicationPaths.ApiAuthorizationPrefix} component={ApiAuthorizationRoutes} />
</Layout>

如果一个未经认证的用户访问一个受保护的路径,他们将被重定向到身份服务器进行认证。很好!

Create React App 3.x

SPA模板使用的Create React App的版本已经从v1提升到v3。但不要太兴奋,React的版本仍然很旧,而且是预先钩住的。TypeScript也被列为依赖项,但该项目似乎并没有使用它:

"dependencies": {
  "babel-eslint": "10.0.1",
  "bootstrap": "^4.1.3",
  "jquery": "^3.4.1",
  "merge": "^1.2.1",
  "oidc-client": "^1.9.0-beta.4",
  "react": "^16.0.0",
  "react-dom": "^16.0.0",
  "react-router-bootstrap": "^0.24.4",
  "react-router-dom": "^4.2.2",
  "react-scripts": "^3.0.1",
  "reactstrap": "^6.3.0",
  "rimraf": "^2.6.2"
},
"devDependencies": {
  "ajv": "^6.9.1",
  "cross-env": "^5.2.0",
  "eslint": "^5.12.0",
  "eslint-config-react-app": "^4.0.1",
  "eslint-plugin-flowtype": "^2.0.0",
  "eslint-plugin-import": "^2.14.0",
  "eslint-plugin-jsx-a11y": "^6.2.1",
  "eslint-plugin-react": "^7.11.1",
  "typescript": "^3.5.2"
}

SignalR端点和自动重新连接

像Web API端点一样,SignalR端点可以使用新的端点路由:

app.UseEndpoints(endpoints =>
{
  endpoints.MapControllers();
  endpoints.MapHub<QuestionsHub>("/questionshub");
});

在React客户端,当建立SignalR连接时,我们可以告诉它在连接丢失时自动重新连接:

const connection = new HubConnectionBuilder()
  .withUrl(`${server}/questionshub`)
  .withAutomaticReconnect()
  .build();