目录


参考文章

    <blockquote>
<ul>
<li><a href="https://www.cnblogs.com/linezero/p/aspnetcorewebapi-restfulapi.html">ASP.NET Core Web API
开发-RESTful API实现</a></li>
<li><a
href="https://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html">理解HTTP幂等性</a>
</li>
<li><a href="https://www.bilibili.com/video/av33344382">某站微软Mvp杨旭的Asp.NetCore
WebApi的视频</a></li>
</ul>
</blockquote>
<hr>
<h2 class="mume-header" id="rest">REST</h2> <p><strong>REST</strong> : <strong>具象状态传输(Representational State
Transfer,简称REST)</strong>,是Roy Thomas
Fielding博士于2000年在他的博士论文
&quot;Architectural Styles and the Design of Network-based Software Architectures&quot;
中提出来的一种万维网软件架构风格。<br>
目前在三种主流的Web服务实现方案中,因为<strong>REST</strong>模式与复杂的<strong>SOAP</strong>和<strong>XML-RPC</strong>相比更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近REST风格的Web服务执行图书查询;
</p>
<p>符合REST设计风格的Web API称为RESTful
API。它从以下三个方面资源进行定义:
</p>
<ul>
<li>直观简短的资源地址:URI,比如:<a
href="http://example.com/resources/">http://example.com/resources/</a> .</li>
<li>传输的资源:Web服务接受与返回的互联网媒体类型,比如:JSON,XML,YAML等...
</li>
<li>对资源的操作:Web服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE).
</li>
</ul>
<p>PUT和DELETE方法是幂等方法.GET方法是安全方法(不会对服务器端有修改,因此当然也是幂等的).
</p>
<p>ps 关于幂等方法 :<br>
看这篇 <a
href="https://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html">理解HTTP幂等性</a>.<br>
简单说,客户端多次请求服务端返回的结果都相同,那么就说这个操作是幂等的.(个人理解,详细的看上面给的文章)
</p>
<p>不像基于SOAP的Web服务,RESTful
Web服务并没有“正式”的标准。这是因为REST是一种架构,而SOAP只是一个协议。虽然REST不是一个标准,但大部分RESTful
Web服务实现会使用HTTP、URI、JSON和XML等各种标准。
</p>
<h2 class="mume-header" id="%E5%B8%B8%E7%94%A8http%E5%8A%A8%E8%AF%8D">常用http动词</h2> <p>括号中是相应的SQL命令.</p>
<ul>
<li><strong>GET(SELECT)</strong> :
从服务器取出资源(一项或多项).
</li>
<li><strong>POST(CREATE)</strong> :
在服务器新建一个资源.</li>
<li><strong>PUT(UPDATE)</strong> :
在服务器更新资源(客户端提供改变后的完整资源).
</li>
<li><strong>PATCH(UPDATE)</strong> :
在服务器更新资源(客户端提供改变的属性).
</li>
<li><strong>DELETE(DELETE)</strong> : 在服务器删除资源.</li>
</ul>
<h2 class="mume-header" id="webapi-%E5%9C%A8-aspnetcore-%E4%B8%AD%E7%9A%84%E5%AE%9E%E7%8E%B0">WebApi 在
Asp.NetCore 中的实现</h2> <p>这里以用户增删改查为例.</p>
<h3 class="mume-header" id="%E5%88%9B%E5%BB%BAwebapi%E9%A1%B9%E7%9B%AE">创建WebApi项目.
</h3> <p>参考<a href="https://www.cnblogs.com/linezero/p/5497472.html">ASP.NET Core WebAPI
开发-新建WebAPI项目</a>.</p>
<p>注意,本文建立的Asp.NetCore <a
href="http://xn--WebApi-177lr63kxhzcdwr.net">WebApi项目选择.net</a>
core版本是<strong>2.2</strong>,不建议使用其他版本,2.1版本下会遇到依赖文件冲突问题!<a
href="http://xn--2-zn6ao2a258ac7hc3a898qg6k.xn--2-856b314a6he.net">所以一定要选择2.2版本的.net</a>
core.</p>
<h3 class="mume-header" id="%E9%9B%86%E6%88%90entity-framework-core%E6%93%8D%E4%BD%9Cmysql">
集成Entity Framework Core操作Mysql</h3> <h4 class="mume-header"
id="%E5%AE%89%E8%A3%85%E7%9B%B8%E5%85%B3%E7%9A%84%E5%8C%85%E4%B8%BAxxxxinfrastructure%E9%A1%B9%E7%9B%AE%E5%AE%89%E8%A3%85">
安装相关的包(为Xxxx.Infrastructure项目安装)
</h4> <ul>
<li>Microsoft.EntityFrameworkCore.Design</li>
<li>Pomelo.EntityFrameworkCore.MySql</li>
</ul>
<p><strong>这里注意一下,Mysql官方的包是
<code>MySql.Data.EntityFrameworkCore</code>,但是这个包有bug,我在github上看到有人说有替代方案
-
<code>Pomelo.EntityFrameworkCore.MySql</code>,经过尝试,后者比前者好用.所有这里就选择后者了.使用前者的话可能会导致数据库迁移失败(Update的时候).</strong>
</p>
<p>PS: Mysql文档原文:</p>
<blockquote>
<p>Install the MySql.Data.EntityFrameworkCore NuGet package.<br>
<strong>For EF Core 1.1 only</strong>: If you plan to scaffold a database, install the
MySql.Data.EntityFrameworkCore.Design NuGet package as well.</p>
<p><a href="https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core.html">EFCore -
MySql文档</a><br>
<strong>Mysql版本要求</strong>:<br>
Mysql版本要高于<strong>5.7</strong><br>
使用最新版本的Mysql Connector(2019 6/27
目前是8.x).</p>
</blockquote>
<p>为Xxxx.<strong>Infrastructure</strong>项目安装EFCore相关的包:<br>
<img src="https://img2018.cnblogs.com/blog/1596066/201906/1596066-20190628014058456-975150311.png" alt></p>
<p>为Xxxx.Api项目安装 <code>Pomelo.EntityFrameworkCore.MySql</code><br>
<img src="https://img2018.cnblogs.com/blog/1596066/201906/1596066-20190628014223270-1330094834.png" alt></p>
<h4 class="mume-header" id="%E5%BB%BA%E7%AB%8Bentity%E5%92%8Ccontext">建立Entity和Context</h4> <p><img src="https://img2018.cnblogs.com/blog/1596066/201906/1596066-20190627231846020-1062185075.png" alt></p>
<details>
<summary>ApiUser</summary>
<pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Core<span class="token punctuation">.</span>Entities

{

using System;

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ApiUser</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token class-name">Guid</span> Guid <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">string</span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">string</span> Passwd <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">DateTime</span> RegistrationDate <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">DateTime</span> Birth <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">string</span> ProfilePhotoUrl <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">string</span> PhoneNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">string</span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

UserContext
namespace ApiStudy.Infrastructure.Database

{

using ApiStudy.Core.Entities;

using Microsoft.EntityFrameworkCore;
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserContext</span><span class="token punctuation">:</span><span class="token class-name">DbContext</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token function">UserContext</span><span class="token punctuation">(</span>DbContextOptions<span class="token operator">&lt;</span>UserContext<span class="token operator">&gt;</span> options<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword">base</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token punctuation">}</span> <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token keyword">void</span> <span class="token function">OnModelCreating</span><span class="token punctuation">(</span><span class="token class-name">ModelBuilder</span> modelBuilder<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
modelBuilder<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Entity</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">HasKey</span><span class="token punctuation">(</span>u <span class="token operator">=&gt;</span> u<span class="token punctuation">.</span>Guid<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">base</span><span class="token punctuation">.</span><span class="token function">OnModelCreating</span><span class="token punctuation">(</span>modelBuilder<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">public</span> DbSet<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> ApiUsers <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

ConfigureService中注入EF服务

    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp">services<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddDbContext</span><span class="token punctuation">&lt;</span><span class="token class-name">UserContext</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>options <span class="token operator">=&gt;</span>
<span class="token punctuation">{</span>
<span class="token keyword">string</span> connString <span class="token operator">=</span> <span class="token string">&quot;Server=Xxx:xxx:xxx:xxx;Database=Xxxx;Uid=root;Pwd=Xxxxx; &quot;</span><span class="token punctuation">;</span>
options<span class="token punctuation">.</span><span class="token function">UseMySQL</span><span class="token punctuation">(</span>connString<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

迁移数据库

    <ul>
<li>在Tools &gt; NuGet Package Manager &gt; Package Manager Console输入命令.
</li>
<li>Add-Migration Xxx 添加迁移.<br>
PS : 如果迁移不想要,使用 Remove-Migration
命令删除迁移.</li>
<li>Update-Database 更新到数据库.</li>
</ul>
<h4 class="mume-header"
id="%E8%BF%81%E7%A7%BB%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%B1%E8%B4%A5-%E6%8F%90%E7%A4%BA-unable-to-create-an-object-of-type-xxxxcontext-for-the-different-patterns-supported-at-design-time-see-httpsgomicrosoftcomfwlinklinkid851728">
迁移数据库失败, 提示 <code>Unable to create an object
of type &apos;&lt;Xxxx&gt;Context&apos;. For the different patterns supported at design time, see
https://go.microsoft.com/fwlink/?linkid=851728</code></h4> <p>原因应该是EfCore迁移工具不知道如何创建
<strong><code>DbContext</code></strong> 导致的.</p>
<p><strong>解决方案</strong></p>
<p>在<code>DbContext</code>所在的项目下新建一个类:
</p>
<pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token comment">/// &lt;summary&gt;</span>

/// 设计时DbContext的创建, 告诉EF Core迁移工具如何创建DbContext

/// </summary>

public class <Xxxx>ContextFactory : IDesignTimeDbContextFactory<<Xxxx>Context>

{

public <Xxxx>Context CreateDbContext(string[] args)

{

var optionsBuilder = new DbContextOptionsBuilder<<Xxxx>Context>();

optionsBuilder.UseMySql(

@"Server=[服务器ip];Database=[数据库]];Uid=[用户名];Pwd=[密码];");

    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token operator">&lt;</span>Xxxx<span class="token operator">&gt;</span><span class="token function">Context</span><span class="token punctuation">(</span>optionsBuilder<span class="token punctuation">.</span>Options<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

数据库迁移结果

    <p><img src="https://img2018.cnblogs.com/blog/1596066/201906/1596066-20190628014343485-1030943357.png" alt></p>
<h4 class="mume-header"
id="326-a-name-1a%E4%B8%BA%E6%95%B0%E6%8D%AE%E5%BA%93%E5%88%9B%E5%BB%BA%E7%A7%8D%E5%AD%90%E6%95%B0%E6%8D%AE">
3.2.6. <a name="-1"
href></a>为数据库创建种子数据</h4> <ul>
<li>
<p>写一个创建种子数据的类</p>
<details>
<summary>UserContextSeed</summary>
<pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Infrastructure<span class="token punctuation">.</span>Database

{

using ApiStudy.Core.Entities;

using Microsoft.Extensions.Logging;

using System;

using System.Linq;

using System.Threading.Tasks;

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserContextSeed</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token class-name">Task</span> <span class="token function">SeedAsync</span><span class="token punctuation">(</span><span class="token class-name">UserContext</span> context<span class="token punctuation">,</span><span class="token class-name">ILoggerFactory</span> loggerFactory<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">try</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>context<span class="token punctuation">.</span>ApiUsers<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
context<span class="token punctuation">.</span>ApiUsers<span class="token punctuation">.</span><span class="token function">AddRange</span><span class="token punctuation">(</span>
<span class="token keyword">new</span> <span class="token class-name">ApiUser</span>
<span class="token punctuation">{</span>
Guid <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Name <span class="token operator">=</span> <span class="token string">&quot;la&quot;</span><span class="token punctuation">,</span>
Birth <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">1998</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">,</span> <span class="token number">29</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
RegistrationDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2019</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">28</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Passwd <span class="token operator">=</span> <span class="token string">&quot;123587&quot;</span><span class="token punctuation">,</span>
ProfilePhotoUrl <span class="token operator">=</span> <span class="token string">&quot;https://www.laggage.top/&quot;</span><span class="token punctuation">,</span>
PhoneNumber <span class="token operator">=</span> <span class="token string">&quot;10086&quot;</span><span class="token punctuation">,</span>
Email <span class="token operator">=</span> <span class="token string">&quot;yu@outlook.com&quot;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">ApiUser</span>
<span class="token punctuation">{</span>
Guid <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Name <span class="token operator">=</span> <span class="token string">&quot;David&quot;</span><span class="token punctuation">,</span>
Birth <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">1995</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">29</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
RegistrationDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2019</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">28</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Passwd <span class="token operator">=</span> <span class="token string">&quot;awt87495987&quot;</span><span class="token punctuation">,</span>
ProfilePhotoUrl <span class="token operator">=</span> <span class="token string">&quot;https://www.laggage.top/&quot;</span><span class="token punctuation">,</span>
PhoneNumber <span class="token operator">=</span> <span class="token string">&quot;1008611&quot;</span><span class="token punctuation">,</span>
Email <span class="token operator">=</span> <span class="token string">&quot;David@outlook.com&quot;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">ApiUser</span>
<span class="token punctuation">{</span>
Guid <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Name <span class="token operator">=</span> <span class="token string">&quot;David&quot;</span><span class="token punctuation">,</span>
Birth <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2001</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">19</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
RegistrationDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2019</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Passwd <span class="token operator">=</span> <span class="token string">&quot;awt87495987&quot;</span><span class="token punctuation">,</span>
ProfilePhotoUrl <span class="token operator">=</span> <span class="token string">&quot;https://www.laggage.top/&quot;</span><span class="token punctuation">,</span>
PhoneNumber <span class="token operator">=</span> <span class="token string">&quot;1008611&quot;</span><span class="token punctuation">,</span>
Email <span class="token operator">=</span> <span class="token string">&quot;David@outlook.com&quot;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">ApiUser</span>
<span class="token punctuation">{</span>
Guid <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Name <span class="token operator">=</span> <span class="token string">&quot;Linus&quot;</span><span class="token punctuation">,</span>
Birth <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">1999</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">26</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
RegistrationDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2018</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Passwd <span class="token operator">=</span> <span class="token string">&quot;awt87495987&quot;</span><span class="token punctuation">,</span>
ProfilePhotoUrl <span class="token operator">=</span> <span class="token string">&quot;https://www.laggage.top/&quot;</span><span class="token punctuation">,</span>
PhoneNumber <span class="token operator">=</span> <span class="token string">&quot;17084759987&quot;</span><span class="token punctuation">,</span>
Email <span class="token operator">=</span> <span class="token string">&quot;Linus@outlook.com&quot;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">ApiUser</span>
<span class="token punctuation">{</span>
Guid <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Name <span class="token operator">=</span> <span class="token string">&quot;YouYou&quot;</span><span class="token punctuation">,</span>
Birth <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">1992</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">26</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
RegistrationDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2015</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Passwd <span class="token operator">=</span> <span class="token string">&quot;grwe874864987&quot;</span><span class="token punctuation">,</span>
ProfilePhotoUrl <span class="token operator">=</span> <span class="token string">&quot;https://www.laggage.top/&quot;</span><span class="token punctuation">,</span>
PhoneNumber <span class="token operator">=</span> <span class="token string">&quot;17084759987&quot;</span><span class="token punctuation">,</span>
Email <span class="token operator">=</span> <span class="token string">&quot;YouYou@outlook.com&quot;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token keyword">new</span> <span class="token class-name">ApiUser</span>
<span class="token punctuation">{</span>
Guid <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Name <span class="token operator">=</span> <span class="token string">&quot;小白&quot;</span><span class="token punctuation">,</span>
Birth <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">1997</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">30</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
RegistrationDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DateTime</span><span class="token punctuation">(</span><span class="token number">2018</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">,</span> <span class="token number">28</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Passwd <span class="token operator">=</span> <span class="token string">&quot;gewa749864&quot;</span><span class="token punctuation">,</span>
ProfilePhotoUrl <span class="token operator">=</span> <span class="token string">&quot;https://www.laggage.top/&quot;</span><span class="token punctuation">,</span>
PhoneNumber <span class="token operator">=</span> <span class="token string">&quot;17084759987&quot;</span><span class="token punctuation">,</span>
Email <span class="token operator">=</span> <span class="token string">&quot;BaiBai@outlook.com&quot;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">await</span> context<span class="token punctuation">.</span><span class="token function">SaveChangesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">catch</span><span class="token punctuation">(</span><span class="token class-name">Exception</span> ex<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token class-name">ILogger</span> logger <span class="token operator">=</span> loggerFactory<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">CreateLogger</span><span class="token punctuation">&lt;</span><span class="token class-name">UserContextSeed</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span>ex<span class="token punctuation">,</span> <span class="token string">&quot;Error occurred while seeding database&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

  • 修改Program.Main方法

    Program.Main
    IWebHost host = CreateWebHostBuilder(args).Build();
    
    using (IServiceScope scope = host.Services.CreateScope())

    {

    IServiceProvider provider = scope.ServiceProvider;

    UserContext userContext = provider.GetService<UserContext>();

    ILoggerFactory loggerFactory = provider.GetService<ILoggerFactory>();

    UserContextSeed.SeedAsync(userContext, loggerFactory).Wait();

    } host.Run();

  • 这个时候运行程序会出现异常,打断点看一下异常信息:Data

    too long for column 'Guid' at row 1

    可以猜到,Mysql的varbinary(16)放不下C#

    Guid.NewGuid()方法生成的Guid,所以配置一下数据库Guid字段类型为varchar(256)可以解决问题.

    解决方案:

    修改 UserContext.OnModelCreating 方法

    配置一下 ApiUser.Guid

    属性到Mysql数据库的映射:

    protected override void OnModelCreating(ModelBuilder modelBuilder)

    {

    modelBuilder.Entity<ApiUser>().Property(p => p.Guid)

    .HasColumnType("nvarchar(256)");

    modelBuilder.Entity<ApiUser>().HasKey(u => u.Guid);
    base.OnModelCreating(modelBuilder);

    }

    支持https

        <p>将所有http请求全部映射到https</p>
    <p>Startup中:<br>
    ConfigureServices方法注册,并配置端口和状态码等:<br>
    services.AddHttpsRedirection(…)</p>
    <pre data-role="codeBlock" data-info class="language-"><code>services.AddHttpsRedirection(options =&gt;
    {
    options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
    options.HttpsPort = 5001;
    });

    Configure方法使用该中间件:

    app.UseHttpsRedirection()

    支持HSTS

        <p>ConfigureServices方法注册<br>
    看<a
    href="https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-2.1&amp;tabs=visual-studio#http-strict-transport-security-protocol-hsts">官方文档</a>
    </p>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp">services<span class="token punctuation">.</span><span class="token function">AddHsts</span><span class="token punctuation">(</span>options <span class="token operator">=&gt;</span>

    {

    options.Preload = true;

    options.IncludeSubDomains = true;

    options.MaxAge = TimeSpan.FromDays(60);

    options.ExcludedHosts.Add("example.com");

    options.ExcludedHosts.Add("www.example.com");

    });

    Configure方法配置中间件管道

    app.UseHsts();

    注意 app.UseHsts() 方法最好放在 app.UseHttps()

    方法之后.

    使用SerilLog

        <p>有关日志的<a
    href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1">微软官方文档</a>
    </p>
    <p>SerilLog <a href="https://github.com/serilog/serilog-aspnetcore">github仓库</a><br>
    该github仓库上有详细的使用说明.</p>
    <p>使用方法:</p>
    <h3 class="mume-header" id="%E5%AE%89%E8%A3%85nuget%E5%8C%85">安装nuget包</h3> <ul>
    <li>Serilog.AspNetCore</li>
    <li>Serilog.Sinks.Console</li>
    </ul>
    <h3 class="mume-header" id="%E6%B7%BB%E5%8A%A0%E4%BB%A3%E7%A0%81">添加代码</h3> <p>Program.Main方法中:</p>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp">Log<span class="token punctuation">.</span>Logger <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LoggerConfiguration</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span>MinimumLevel<span class="token punctuation">.</span><span class="token function">Debug</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span>MinimumLevel<span class="token punctuation">.</span><span class="token function">Override</span><span class="token punctuation">(</span><span class="token string">&quot;Microsoft&quot;</span><span class="token punctuation">,</span> LogEventLevel<span class="token punctuation">.</span>Information<span class="token punctuation">)</span>
    <span class="token punctuation">.</span>Enrich<span class="token punctuation">.</span><span class="token function">FromLogContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span>WriteTo<span class="token punctuation">.</span><span class="token function">Console</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">CreateLogger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    修改Program.CreateWebHostBuilder(...)

     public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .UseSerilog(); // <-- Add this line;
    }

    自行测试

        <h2 class="mume-header" id="aspnetcore%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6">
    Asp.NetCore配置文件</h2> <h3 class="mume-header" id="%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6">
    默认配置文件</h3> <p>默认 appsettings.json<br>
    ConfigurationBuilder().AddJsonFile(&quot;appsettings.json&quot;).Build()--&gt;IConfigurationRoot(IConfiguration)
    </p>
    <h3 class="mume-header" id="%E8%8E%B7%E5%BE%97%E9%85%8D%E7%BD%AE">获得配置</h3> <p>IConfiguration[“Key:ChildKey”]<br>
    针对”ConnectionStrings:xxx”,可以使用IConfiguration.GetConnectionString(“xxx”)
    </p>
    <pre data-role="codeBlock" data-info class="language-"><code>private static IConfiguration Configuration { get; set; }

    public StartupDevelopment(IConfiguration config)

    {

    Configuration = config;

    }

    ...

    Configuration[“Key:ChildKey”]

    自定义一个异常处理,ExceptionHandler

        <h3 class="mume-header"
    id="%E5%BC%84%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%86%99%E4%B8%80%E4%B8%AA%E6%89%A9%E5%B1%95%E6%96%B9%E6%B3%95%E5%A4%84%E7%90%86%E5%BC%82%E5%B8%B8">
    弄一个类,写一个扩展方法处理异常
    </h3> <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Api<span class="token punctuation">.</span>Extensions

    {

    using Microsoft.AspNetCore.Builder;

    using Microsoft.AspNetCore.Http;

    using Microsoft.Extensions.Logging;

    using System;

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">ExceptionHandlingExtensions</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">UseCustomExceptionHandler</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">IApplicationBuilder</span> app<span class="token punctuation">,</span><span class="token class-name">ILoggerFactory</span> loggerFactory<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    app<span class="token punctuation">.</span><span class="token function">UseExceptionHandler</span><span class="token punctuation">(</span>
    builder <span class="token operator">=&gt;</span> builder<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token keyword">async</span> context <span class="token operator">=&gt;</span>
    <span class="token punctuation">{</span>
    context<span class="token punctuation">.</span>Response<span class="token punctuation">.</span>StatusCode <span class="token operator">=</span> StatusCodes<span class="token punctuation">.</span>Status500InternalServerError<span class="token punctuation">;</span>
    context<span class="token punctuation">.</span>Response<span class="token punctuation">.</span>ContentType <span class="token operator">=</span> <span class="token string">&quot;application/json&quot;</span><span class="token punctuation">;</span> <span class="token class-name">Exception</span> ex <span class="token operator">=</span> context<span class="token punctuation">.</span>Features<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Get</span><span class="token punctuation">&lt;</span><span class="token class-name">Exception</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token punctuation">(</span>ex <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token class-name">ILogger</span> logger <span class="token operator">=</span> loggerFactory<span class="token punctuation">.</span><span class="token function">CreateLogger</span><span class="token punctuation">(</span><span class="token string">&quot;ApiStudy.Api.Extensions.ExceptionHandlingExtensions&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    logger<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span>ex<span class="token punctuation">,</span> <span class="token string">&quot;Error occurred.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">await</span> context<span class="token punctuation">.</span>Response<span class="token punctuation">.</span><span class="token function">WriteAsync</span><span class="token punctuation">(</span>ex<span class="token punctuation">?.</span>Message <span class="token operator">??</span> <span class="token string">&quot;Error occurred, but cannot get exception message.For more detail, go to see the log.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    在Configuration中使用扩展方法

        <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token comment">// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.</span>

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)

    {

    app.UseCustomExceptionHandler(loggerFactory); //modified code

    <span class="token comment">//app.UseDeveloperExceptionPage();</span>
    app<span class="token punctuation">.</span><span class="token function">UseHsts</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    app<span class="token punctuation">.</span><span class="token function">UseHttpsRedirection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token function">UseMvc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//使用默认路由</span>

    }

    实现数据接口类(Resource),使用AutoMapper在Resource和Entity中映射

        <h3 class="mume-header"
    id="91-a-nameentityresourcea%E4%B8%BAentity%E7%B1%BB%E5%88%9B%E5%BB%BA%E5%AF%B9%E5%BA%94%E7%9A%84resource%E7%B1%BB">
    9.1. <a name="EntityResource"
    href></a>为Entity类创建对应的Resource类</h3> <details>
    <summary>ApiUserResource</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Infrastructure<span class="token punctuation">.</span>Resources

    {

    using System;

    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ApiUserResource</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token class-name">Guid</span> Guid <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token comment">//public string Passwd { get; set; }</span>
    <span class="token keyword">public</span> <span class="token class-name">DateTime</span> RegistrationDate <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token class-name">DateTime</span> Birth <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> ProfilePhotoUrl <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> PhoneNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    使用 AutoMapper

        <ul>
    <li>
    <p>添加nuget包<br>
    <code>AutoMapper</code><br>
    <code>AutoMapper.Extensions.Microsoft.DependencyInjection</code></p>
    </li>
    <li>
    <p>配置映射<br>
    可以创建Profile<br>
    CreateMap&lt;TSource,TDestination&gt;()</p>
    <details>
    <summary>MappingProfile</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Api<span class="token punctuation">.</span>Extensions

    {

    using ApiStudy.Core.Entities;

    using ApiStudy.Infrastructure.Resources;

    using AutoMapper;

    using System;

    using System.Text;

    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MappingProfile</span> <span class="token punctuation">:</span> <span class="token class-name">Profile</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token function">MappingProfile</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token generic-method"><span class="token function">CreateMap</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">,</span> <span class="token class-name">ApiUserResource</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">ForMember</span><span class="token punctuation">(</span>
    d <span class="token operator">=&gt;</span> d<span class="token punctuation">.</span>Passwd<span class="token punctuation">,</span>
    opt <span class="token operator">=&gt;</span> opt<span class="token punctuation">.</span><span class="token function">AddTransform</span><span class="token punctuation">(</span>s <span class="token operator">=&gt;</span> Convert<span class="token punctuation">.</span><span class="token function">ToBase64String</span><span class="token punctuation">(</span>Encoding<span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">GetBytes</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token generic-method"><span class="token function">CreateMap</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">ForMember</span><span class="token punctuation">(</span>
    d <span class="token operator">=&gt;</span> d<span class="token punctuation">.</span>Passwd<span class="token punctuation">,</span>
    opt <span class="token operator">=&gt;</span> opt<span class="token punctuation">.</span><span class="token function">AddTransform</span><span class="token punctuation">(</span>s <span class="token operator">=&gt;</span> Encoding<span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">GetString</span><span class="token punctuation">(</span>Convert<span class="token punctuation">.</span><span class="token function">FromBase64String</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

  • 注入服务 -> services.AddAutoMapper()

  • 使用FluentValidation

        <p><a href="https://fluentvalidation.net/">FluentValidation官网</a></p>
    <h3 class="mume-header" id="%E5%AE%89%E8%A3%85nuget%E5%8C%85-1">安装Nuget包</h3> <ul>
    <li>FluentValidation</li>
    <li>FluentValidation.AspNetCore</li>
    </ul>
    <h3 class="mume-header"
    id="%E4%B8%BA%E6%AF%8F%E4%B8%80%E4%B8%AAresource%E9%85%8D%E7%BD%AE%E9%AA%8C%E8%AF%81%E5%99%A8">
    为每一个Resource配置验证器</h3> <ul>
    <li>
    <p>继承于AbstractValidator</p>
    <details>
    <summary>ApiUserResourceValidator </summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Infrastructure<span class="token punctuation">.</span>Resources

    {

    using FluentValidation;

    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ApiUserResourceValidator</span> <span class="token punctuation">:</span> <span class="token class-name">AbstractValidator</span><span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token function">ApiUserResourceValidator</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token function">RuleFor</span><span class="token punctuation">(</span>s <span class="token operator">=&gt;</span> s<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">MaximumLength</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">&quot;用户名&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}的最大长度为80&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}不能为空!&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

  • 注册到容器:services.AddTransient<>()

    services.AddTransient<IValidator<ApiUserResource>,

    ApiUserResourceValidator>();

  • 实现Http Get(翻页,过滤,排序)

        <details>
    <summary>基本的Get实现</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token punctuation">[</span><span class="token class-name">HttpGet</span><span class="token punctuation">]</span>

    public async Task<IActionResult> Get()

    {

    IEnumerable<ApiUser> apiUsers = await _apiUserRepository.GetAllApiUsersAsync();

    IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span>IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>apiUserResources<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    [HttpGet("{guid}")]

    public async Task<IActionResult> Get(string guid)

    {

    ApiUser apiUser = await _apiUserRepository.GetApiUserByGuidAsync(Guid.Parse(guid));

    <span class="token keyword">if</span> <span class="token punctuation">(</span>apiUser <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token class-name">ApiUserResource</span> apiUserResource <span class="token operator">=</span> _mapper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Map</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">,</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>apiUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>apiUserResource<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    资源命名

        <h4 class="mume-header" id="%E8%B5%84%E6%BA%90%E5%BA%94%E8%AF%A5%E4%BD%BF%E7%94%A8%E5%90%8D%E8%AF%8D%E4%BE%8B">
    资源应该使用名词,例</h4> <ul>
    <li>api/getusers就是不正确的.</li>
    <li><strong>GET api/users</strong>就是正确的</li>
    </ul>
    <h4 class="mume-header" id="%E8%B5%84%E6%BA%90%E5%91%BD%E5%90%8D%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84">
    资源命名层次结构</h4> <ul>
    <li>例如<code>api/department/{departmentId}/emoloyees</code>,
    这就表示了 <code>department</code>
    (部门)和员工<br>
    (<strong>employee</strong>)之前是主从关系.</li>
    <li>而<code>api/department/{departmentId}/emoloyees/{employeeId}</code>,就表示了该部门下的某个员<br>
    工.</li>
    </ul>
    <h3 class="mume-header" id="%E5%86%85%E5%AE%B9%E5%8D%8F%E5%95%86">内容协商</h3> <p><a href="http://ASP.NET">ASP.NET</a>
    Core支持输出和输入两种格式化器.
    </p>
    <ul>
    <li>用于输出的media type放在<strong>Accept
    Header</strong>里,表示客户端接受这种格式的输出.
    </li>
    <li>用于输入的media type放<strong>Content-Type</strong>
    Header里,表示客户端传进来的数据是这种格式.
    </li>
    <li><strong>ReturnHttpNotAcceptable</strong>设为true,如果客户端请求不支持的数据格式,就会返回406.
    <pre data-role="codeBlock" data-info class="language-"><code>services.AddMvc(options =&gt;

    {

    options.ReturnHttpNotAcceptable = true;

    });

  • 支持输出XML格式:options.OutputFormatters.Add(newXmlDataContractSerializerOutputFormatter());
  • 翻页

        <h3 class="mume-header" id="%E6%9E%84%E9%80%A0%E7%BF%BB%E9%A1%B5%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E7%B1%BB">
    构造翻页请求参数类</h3> <details>
    <summary>QueryParameters</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Core<span class="token punctuation">.</span>Entities

    {

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Runtime.CompilerServices;

    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">QueryParameters</span> <span class="token punctuation">:</span> <span class="token class-name">INotifyPropertyChanged</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">event</span> <span class="token class-name">PropertyChangedEventHandler</span> PropertyChanged<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token keyword">int</span> DefaultPageSize <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">const</span> <span class="token keyword">int</span> DefaultMaxPageSize <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token keyword">int</span> _pageIndex <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token keyword">int</span> PageIndex
    <span class="token punctuation">{</span>
    <span class="token keyword">get</span> <span class="token operator">=&gt;</span> _pageIndex<span class="token punctuation">;</span>
    <span class="token keyword">set</span> <span class="token operator">=&gt;</span> <span class="token function">SetField</span><span class="token punctuation">(</span><span class="token keyword">ref</span> _pageIndex<span class="token punctuation">,</span> <span class="token keyword">value</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">int</span> _pageSize <span class="token operator">=</span> DefaultPageSize<span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token keyword">int</span> PageSize
    <span class="token punctuation">{</span>
    <span class="token keyword">get</span> <span class="token operator">=&gt;</span> _pageSize<span class="token punctuation">;</span>
    <span class="token keyword">set</span> <span class="token operator">=&gt;</span> <span class="token function">SetField</span><span class="token punctuation">(</span><span class="token keyword">ref</span> _pageSize<span class="token punctuation">,</span> <span class="token keyword">value</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">int</span> _maxPageSize <span class="token operator">=</span> DefaultMaxPageSize<span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">virtual</span> <span class="token keyword">int</span> MaxPageSize
    <span class="token punctuation">{</span>
    <span class="token keyword">get</span> <span class="token operator">=&gt;</span> _maxPageSize<span class="token punctuation">;</span>
    <span class="token keyword">set</span> <span class="token operator">=&gt;</span> <span class="token function">SetField</span><span class="token punctuation">(</span><span class="token keyword">ref</span> _maxPageSize<span class="token punctuation">,</span> <span class="token keyword">value</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">string</span> OrderBy <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Fields <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token generic-method"><span class="token function">SetField</span><span class="token punctuation">&lt;</span><span class="token class-name">TField</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>
    <span class="token keyword">ref</span> <span class="token class-name">TField</span> field<span class="token punctuation">,</span><span class="token keyword">in</span> <span class="token class-name">TField</span> newValue<span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token class-name">CallerMemberName</span><span class="token punctuation">]</span> <span class="token keyword">string</span> propertyName <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>EqualityComparer<span class="token operator">&lt;</span>TField<span class="token operator">&gt;</span><span class="token punctuation">.</span>Default<span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>field<span class="token punctuation">,</span> newValue<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span><span class="token punctuation">;</span>
    field <span class="token operator">=</span> newValue<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>propertyName <span class="token operator">==</span> <span class="token function">nameof</span><span class="token punctuation">(</span>PageSize<span class="token punctuation">)</span> <span class="token operator">||</span> propertyName <span class="token operator">==</span> <span class="token function">nameof</span><span class="token punctuation">(</span>MaxPageSize<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token function">SetPageSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> PropertyChanged<span class="token punctuation">?.</span><span class="token function">Invoke</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">PropertyChangedEventArgs</span><span class="token punctuation">(</span>propertyName<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">SetPageSize</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>_maxPageSize <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span> _maxPageSize <span class="token operator">=</span> DefaultMaxPageSize<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>_pageSize <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span> _pageSize <span class="token operator">=</span> DefaultPageSize<span class="token punctuation">;</span>
    _pageSize <span class="token operator">=</span> _pageSize <span class="token operator">&gt;</span> _maxPageSize <span class="token punctuation">?</span> _maxPageSize <span class="token punctuation">:</span> _pageSize<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    ApiUserParameters
    namespace ApiStudy.Core.Entities

    {

    public class ApiUserParameters:QueryParameters

    {

    public string UserName { get; set; }

    }

    }

    Repository实现支持翻页请求参数的方法

        <details>
    <summary>Repository相关代码</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token comment">/*----- ApiUserRepository -----*/</span>

    public PaginatedList<ApiUser> GetAllApiUsers(ApiUserParameters parameters)

    {

    return new PaginatedList<ApiUser>(

    parameters.PageIndex,

    parameters.PageSize,

    _context.ApiUsers.Count(),

    _context.ApiUsers.Skip(parameters.PageIndex * parameters.PageSize)

    .Take(parameters.PageSize));

    }

    public Task<PaginatedList<ApiUser>> GetAllApiUsersAsync(ApiUserParameters parameters)

    {

    return Task.Run(() => GetAllApiUsers(parameters));

    }

    /----- IApiUserRepository -----/

    PaginatedList<ApiUser> GetAllApiUsers(ApiUserParameters parameters);

    Task<PaginatedList<ApiUser>> GetAllApiUsersAsync(ApiUserParameters parameters);

    UserController部分代码
    ...
    
    [HttpGet(Name = "GetAllApiUsers")]

    public async Task<IActionResult> GetAllApiUsers(ApiUserParameters parameters)

    {

    PaginatedList<ApiUser> apiUsers = await _apiUserRepository.GetAllApiUsersAsync(parameters);
    IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span>IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> meta <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    PageIndex <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>PageIndex<span class="token punctuation">,</span>
    PageSize <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>PageSize<span class="token punctuation">,</span>
    PageCount <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>PageCount<span class="token punctuation">,</span>
    TotalItemsCount <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>TotalItemsCount<span class="token punctuation">,</span>
    NextPageUrl <span class="token operator">=</span> <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>NextPage<span class="token punctuation">)</span><span class="token punctuation">,</span>
    PreviousPageUrl <span class="token operator">=</span> <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>PreviousPage<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
    Response<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token string">&quot;X-Pagination&quot;</span><span class="token punctuation">,</span>
    JsonConvert<span class="token punctuation">.</span><span class="token function">SerializeObject</span><span class="token punctuation">(</span>
    meta<span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">JsonSerializerSettings</span>
    <span class="token punctuation">{</span> ContractResolver <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CamelCasePropertyNamesContractResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>apiUserResources<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    ...

    private string CreateApiUserUrl(ApiUserParameters parameters,ResourceUriType uriType)

    {

    var param = new ApiUserParameters

    {

    PageIndex = parameters.PageIndex,

    PageSize = parameters.PageSize

    };

    switch (uriType)

    {

    case ResourceUriType.PreviousPage:

    param.PageIndex--;

    break;

    case ResourceUriType.NextPage:

    param.PageIndex++;

    break;

    case ResourceUriType.CurrentPage:

    break;

    default:break;

    }

    return Url.Link("GetAllApiUsers", parameters);

    }

    PS注意,为HttpGet方法添加参数的话,在.net

    core2.2版本下,去掉那个ApiUserController上的

    [ApiController());] 特性,否则参数传不进来..net

    core3.0中据说已经修复这个问题.

    搜索(过滤)

        <p>修改Repository代码:</p>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"> <span class="token keyword">public</span> PaginatedList<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> <span class="token function">GetAllApiUsers</span><span class="token punctuation">(</span><span class="token class-name">ApiUserParameters</span> parameters<span class="token punctuation">)</span>

    {

    IQueryable<ApiUser> query = _context.ApiUsers.AsQueryable();

    query = query.Skip(parameters.PageIndex * parameters.PageSize)

    .Take(parameters.PageSize);

    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>UserName<span class="token punctuation">)</span><span class="token punctuation">)</span>
    query <span class="token operator">=</span> _context<span class="token punctuation">.</span>ApiUsers<span class="token punctuation">.</span><span class="token function">Where</span><span class="token punctuation">(</span>
    x <span class="token operator">=&gt;</span> StringComparer<span class="token punctuation">.</span>OrdinalIgnoreCase<span class="token punctuation">.</span><span class="token function">Compare</span><span class="token punctuation">(</span>x<span class="token punctuation">.</span>Name<span class="token punctuation">,</span> parameters<span class="token punctuation">.</span>UserName<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token generic-method"><span class="token function">PaginatedList</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>
    parameters<span class="token punctuation">.</span>PageIndex<span class="token punctuation">,</span>
    parameters<span class="token punctuation">.</span>PageSize<span class="token punctuation">,</span>
    query<span class="token punctuation">.</span><span class="token function">Count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    query<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    排序

        <h4 class="mume-header" id="%E6%8E%92%E5%BA%8F%E6%80%9D%E8%B7%AF">&gt;排序思路</h4>
    
        <ul>
    <li>需要安装System.Linq.Dynamic.Core</li>
    </ul>
    <p><strong>思路</strong>:</p>
    <ul>
    <li>PropertyMappingContainer
    <ul>
    <li>PropertyMapping(ApiUserPropertyMapping)
    <ul>
    <li>MappedProperty</li>
    </ul>
    </li>
    </ul>
    </li>
    </ul>
    <details>
    <summary>MappedProperty</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Infrastructure<span class="token punctuation">.</span>Services

    {

    public struct MappedProperty

    {

    public MappedProperty(string name, bool revert = false)

    {

    Name = name;

    Revert = revert;

    }

        <span class="token keyword">public</span> <span class="token keyword">string</span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">bool</span> Revert <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    IPropertyMapping
    namespace ApiStudy.Infrastructure.Services

    {

    using System.Collections.Generic;
    <span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">IPropertyMapping</span>
    <span class="token punctuation">{</span>
    Dictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> List<span class="token operator">&lt;</span>MappedProperty<span class="token operator">&gt;&gt;</span> MappingDictionary <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    PropertyMapping
    namespace ApiStudy.Infrastructure.Services

    {

    using System.Collections.Generic;
    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">PropertyMapping</span><span class="token operator">&lt;</span>TSource<span class="token punctuation">,</span>TDestination<span class="token operator">&gt;</span> <span class="token punctuation">:</span> IPropertyMapping
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> Dictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> List<span class="token operator">&lt;</span>MappedProperty<span class="token operator">&gt;&gt;</span> MappingDictionary <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token function">PropertyMapping</span><span class="token punctuation">(</span>Dictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> List<span class="token operator">&lt;</span>MappedProperty<span class="token operator">&gt;&gt;</span> MappingDict<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    MappingDictionary <span class="token operator">=</span> MappingDict<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    IPropertyMappingContainer
    namespace ApiStudy.Infrastructure.Services

    {

    public interface IPropertyMappingContainer

    {

    void Register<T>() where T : IPropertyMapping, new();

    IPropertyMapping Resolve<TSource, TDestination>();

    bool ValidateMappingExistsFor<TSource, TDestination>(string fields);

    }

    }

    PropertyMappingContainer
    namespace ApiStudy.Infrastructure.Services

    {

    using System;

    using System.Linq;

    using System.Collections.Generic;
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PropertyMappingContainer</span> <span class="token punctuation">:</span> <span class="token class-name">IPropertyMappingContainer</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token keyword">internal</span> <span class="token keyword">readonly</span> IList<span class="token operator">&lt;</span>IPropertyMapping<span class="token operator">&gt;</span> PropertyMappings <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token generic-method"><span class="token function">List</span><span class="token punctuation">&lt;</span><span class="token class-name">IPropertyMapping</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token generic-method"><span class="token function">Register</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">where</span> T <span class="token punctuation">:</span> IPropertyMapping<span class="token punctuation">,</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>PropertyMappings<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span><span class="token function">GetType</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token keyword">typeof</span><span class="token punctuation">(</span>T<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>
    PropertyMappings<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">T</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">public</span> IPropertyMapping <span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">TSource</span><span class="token punctuation">,</span><span class="token class-name">TDestination</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    IEnumerable<span class="token operator">&lt;</span>PropertyMapping<span class="token operator">&lt;</span>TSource<span class="token punctuation">,</span> TDestination<span class="token operator">&gt;&gt;</span> result <span class="token operator">=</span> PropertyMappings<span class="token punctuation">.</span>OfType<span class="token operator">&lt;</span>PropertyMapping<span class="token operator">&lt;</span>TSource<span class="token punctuation">,</span>TDestination<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">.</span><span class="token function">Count</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> result<span class="token punctuation">.</span><span class="token function">First</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InvalidCastException</span><span class="token punctuation">(</span>
    <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Format</span><span class="token punctuation">(</span> <span class="token string">&quot;Cannot find property mapping instance for {0}, {1}&quot;</span><span class="token punctuation">,</span> <span class="token keyword">typeof</span><span class="token punctuation">(</span>TSource<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">typeof</span><span class="token punctuation">(</span>TDestination<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">bool</span> <span class="token generic-method"><span class="token function">ValidateMappingExistsFor</span><span class="token punctuation">&lt;</span><span class="token class-name">TSource</span><span class="token punctuation">,</span> <span class="token class-name">TDestination</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token keyword">string</span> fields<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">true</span><span class="token punctuation">;</span> <span class="token class-name">IPropertyMapping</span> propertyMapping <span class="token operator">=</span> <span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">TSource</span><span class="token punctuation">,</span> <span class="token class-name">TDestination</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> splitFields <span class="token operator">=</span> fields<span class="token punctuation">.</span><span class="token function">Split</span><span class="token punctuation">(</span><span class="token string">&apos;,&apos;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">foreach</span><span class="token punctuation">(</span><span class="token keyword">string</span> property <span class="token keyword">in</span> splitFields<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">string</span> trimmedProperty <span class="token operator">=</span> property<span class="token punctuation">.</span><span class="token function">Trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">int</span> indexOfFirstWhiteSpace <span class="token operator">=</span> trimmedProperty<span class="token punctuation">.</span><span class="token function">IndexOf</span><span class="token punctuation">(</span><span class="token string">&apos; &apos;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">string</span> propertyName <span class="token operator">=</span> indexOfFirstWhiteSpace <span class="token operator">&lt;=</span> <span class="token number">0</span> <span class="token punctuation">?</span> trimmedProperty <span class="token punctuation">:</span> trimmedProperty<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span>indexOfFirstWhiteSpace<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>propertyMapping<span class="token punctuation">.</span>MappingDictionary<span class="token punctuation">.</span>Keys<span class="token punctuation">.</span><span class="token function">Any</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>propertyName<span class="token punctuation">,</span>x<span class="token punctuation">,</span>StringComparison<span class="token punctuation">.</span>OrdinalIgnoreCase<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    QueryExtensions
    namespace ApiStudy.Infrastructure.Extensions

    {

    using ApiStudy.Infrastructure.Services;

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Linq.Dynamic.Core;
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">QueryExtensions</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> IQueryable<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token generic-method"><span class="token function">ApplySort</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>
    <span class="token keyword">this</span> IQueryable<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> data<span class="token punctuation">,</span><span class="token keyword">in</span> <span class="token keyword">string</span> orderBy<span class="token punctuation">,</span><span class="token keyword">in</span> <span class="token class-name">IPropertyMapping</span> propertyMapping<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>data <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ArgumentNullException</span><span class="token punctuation">(</span><span class="token function">nameof</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>orderBy<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> data<span class="token punctuation">;</span> <span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> splitOrderBy <span class="token operator">=</span> orderBy<span class="token punctuation">.</span><span class="token function">Split</span><span class="token punctuation">(</span><span class="token string">&apos;,&apos;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">foreach</span><span class="token punctuation">(</span><span class="token keyword">string</span> property <span class="token keyword">in</span> splitOrderBy<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">string</span> trimmedProperty <span class="token operator">=</span> property<span class="token punctuation">.</span><span class="token function">Trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">int</span> indexOfFirstSpace <span class="token operator">=</span> trimmedProperty<span class="token punctuation">.</span><span class="token function">IndexOf</span><span class="token punctuation">(</span><span class="token string">&apos; &apos;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">bool</span> desc <span class="token operator">=</span> trimmedProperty<span class="token punctuation">.</span><span class="token function">EndsWith</span><span class="token punctuation">(</span><span class="token string">&quot; desc&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">string</span> propertyName <span class="token operator">=</span> indexOfFirstSpace <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token punctuation">?</span> trimmedProperty<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span>indexOfFirstSpace<span class="token punctuation">)</span> <span class="token punctuation">:</span> trimmedProperty<span class="token punctuation">;</span>
    propertyName <span class="token operator">=</span> propertyMapping<span class="token punctuation">.</span>MappingDictionary<span class="token punctuation">.</span>Keys<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>
    x <span class="token operator">=&gt;</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> propertyName<span class="token punctuation">,</span> StringComparison<span class="token punctuation">.</span>OrdinalIgnoreCase<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//ignore case of sort property</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>propertyMapping<span class="token punctuation">.</span>MappingDictionary<span class="token punctuation">.</span><span class="token function">TryGetValue</span><span class="token punctuation">(</span>
    propertyName<span class="token punctuation">,</span> <span class="token keyword">out</span> List<span class="token operator">&lt;</span>MappedProperty<span class="token operator">&gt;</span> mappedProperties<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InvalidCastException</span><span class="token punctuation">(</span>$<span class="token string">&quot;key mapping for {propertyName} is missing&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> mappedProperties<span class="token punctuation">.</span><span class="token function">Reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">foreach</span><span class="token punctuation">(</span><span class="token class-name">MappedProperty</span> mappedProperty <span class="token keyword">in</span> mappedProperties<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mappedProperty<span class="token punctuation">.</span>Revert<span class="token punctuation">)</span> desc <span class="token operator">=</span> <span class="token operator">!</span>desc<span class="token punctuation">;</span>
    data <span class="token operator">=</span> data<span class="token punctuation">.</span><span class="token function">OrderBy</span><span class="token punctuation">(</span>$<span class="token string">&quot;{mappedProperty.Name} {(desc ? &quot;</span><span class="token keyword">descending</span><span class="token string">&quot; : &quot;</span><span class="token keyword">ascending</span><span class="token string">&quot;)} &quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> data<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    UserController 部分代码
    [HttpGet(Name = "GetAllApiUsers")]

    public async Task<IActionResult> GetAllApiUsers(ApiUserParameters parameters)

    {

    if (!_propertyMappingContainer.ValidateMappingExistsFor<ApiUserResource, ApiUser>(parameters.OrderBy))

    return BadRequest("can't find fields for sorting.");
    PaginatedList<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> apiUsers <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetAllApiUsersAsync</span><span class="token punctuation">(</span>parameters<span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> sortedApiUserResources <span class="token operator">=</span>
    apiUserResources<span class="token punctuation">.</span><span class="token function">AsQueryable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ApplySort</span><span class="token punctuation">(</span>
    parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">,</span> _propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> meta <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    apiUsers<span class="token punctuation">.</span>PageIndex<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageSize<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageCount<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>TotalItemsCount<span class="token punctuation">,</span>
    PreviousPageUrl <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>HasPreviousPage <span class="token punctuation">?</span> <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>PreviousPage<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">,</span>
    NextPageUrl <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>HasNextPage <span class="token punctuation">?</span> <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>NextPage<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
    Response<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token string">&quot;X-Pagination&quot;</span><span class="token punctuation">,</span>
    JsonConvert<span class="token punctuation">.</span><span class="token function">SerializeObject</span><span class="token punctuation">(</span>
    meta<span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">JsonSerializerSettings</span>
    <span class="token punctuation">{</span> ContractResolver <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CamelCasePropertyNamesContractResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>sortedApiUserResources<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    private string CreateApiUserUrl(ApiUserParameters parameters, ResourceUriType uriType)

    {

    var param = new {

    parameters.PageIndex,

    parameters.PageSize

    };

    switch (uriType)

    {

    case ResourceUriType.PreviousPage:

    param = new

    {

    PageIndex = parameters.PageIndex - 1,

    parameters.PageSize

    };

    break;

    case ResourceUriType.NextPage:

    param = new

    {

    PageIndex = parameters.PageIndex + 1,

    parameters.PageSize

    };

    break;

    case ResourceUriType.CurrentPage:

    break;

    default: break;

    }

    return Url.Link("GetAllApiUsers", param);

    }

    资源塑形(Resource shaping)

        <p>返回 资源的指定字段</p>
    <details>
    <summary>ApiStudy.Infrastructure.Extensions.TypeExtensions</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Infrastructure<span class="token punctuation">.</span>Extensions

    {

    using System;

    using System.Collections.Generic;

    using System.Reflection;

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">TypeExtensions</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> IEnumerable<span class="token operator">&lt;</span>PropertyInfo<span class="token operator">&gt;</span> <span class="token function">GetProeprties</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token class-name">Type</span> source<span class="token punctuation">,</span> <span class="token keyword">string</span> fields <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    List<span class="token operator">&lt;</span>PropertyInfo<span class="token operator">&gt;</span> propertyInfoList <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token generic-method"><span class="token function">List</span><span class="token punctuation">&lt;</span><span class="token class-name">PropertyInfo</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    propertyInfoList<span class="token punctuation">.</span><span class="token function">AddRange</span><span class="token punctuation">(</span>source<span class="token punctuation">.</span><span class="token function">GetProperties</span><span class="token punctuation">(</span>BindingFlags<span class="token punctuation">.</span>Public <span class="token operator">|</span> BindingFlags<span class="token punctuation">.</span>Instance<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">else</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> properties <span class="token operator">=</span> fields<span class="token punctuation">.</span><span class="token function">Trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Split</span><span class="token punctuation">(</span><span class="token string">&apos;,&apos;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token keyword">string</span> propertyName <span class="token keyword">in</span> properties<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    propertyInfoList<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    source<span class="token punctuation">.</span><span class="token function">GetProperty</span><span class="token punctuation">(</span>
    propertyName<span class="token punctuation">.</span><span class="token function">Trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    BindingFlags<span class="token punctuation">.</span>Public <span class="token operator">|</span> BindingFlags<span class="token punctuation">.</span>Instance <span class="token operator">|</span> BindingFlags<span class="token punctuation">.</span>IgnoreCase<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> propertyInfoList<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    ApiStudy.Infrastructure.Extensions.ObjectExtensions
    namespace ApiStudy.Infrastructure.Extensions

    {

    using System.Collections.Generic;

    using System.Dynamic;

    using System.Linq;

    using System.Reflection;
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">ObjectExtensions</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">ExpandoObject</span> <span class="token function">ToDynamicObject</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token keyword">object</span> source<span class="token punctuation">,</span> <span class="token keyword">in</span> <span class="token keyword">string</span> fields <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    List<span class="token operator">&lt;</span>PropertyInfo<span class="token operator">&gt;</span> propertyInfoList <span class="token operator">=</span> source<span class="token punctuation">.</span><span class="token function">GetType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">GetProeprties</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">ExpandoObject</span> expandoObject <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ExpandoObject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token class-name">PropertyInfo</span> propertyInfo <span class="token keyword">in</span> propertyInfoList<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">try</span>
    <span class="token punctuation">{</span>
    <span class="token punctuation">(</span>expandoObject <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    propertyInfo<span class="token punctuation">.</span>Name<span class="token punctuation">,</span> propertyInfo<span class="token punctuation">.</span><span class="token function">GetValue</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">catch</span> <span class="token punctuation">{</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> expandoObject<span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">internal</span> <span class="token keyword">static</span> <span class="token class-name">ExpandoObject</span> <span class="token function">ToDynamicObject</span><span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token keyword">object</span> source<span class="token punctuation">,</span> <span class="token keyword">in</span> IEnumerable<span class="token operator">&lt;</span>PropertyInfo<span class="token operator">&gt;</span> propertyInfos<span class="token punctuation">,</span> <span class="token keyword">in</span> <span class="token keyword">string</span> fields <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token class-name">ExpandoObject</span> expandoObject <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ExpandoObject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token class-name">PropertyInfo</span> propertyInfo <span class="token keyword">in</span> propertyInfos<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">try</span>
    <span class="token punctuation">{</span>
    <span class="token punctuation">(</span>expandoObject <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    propertyInfo<span class="token punctuation">.</span>Name<span class="token punctuation">,</span> propertyInfo<span class="token punctuation">.</span><span class="token function">GetValue</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">catch</span> <span class="token punctuation">{</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> expandoObject<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    ApiStudy.Infrastructure.Extensions.IEnumerableExtensions
    namespace ApiStudy.Infrastructure.Extensions

    {

    using System;

    using System.Collections.Generic;

    using System.Dynamic;

    using System.Linq;

    using System.Reflection;
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">IEnumerableExtensions</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> <span class="token generic-method"><span class="token function">ToDynamicObject</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>
    <span class="token keyword">this</span> IEnumerable<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> source<span class="token punctuation">,</span><span class="token keyword">in</span> <span class="token keyword">string</span> fields <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>source <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ArgumentNullException</span><span class="token punctuation">(</span><span class="token function">nameof</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> List<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> expandoObejctList <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token generic-method"><span class="token function">List</span><span class="token punctuation">&lt;</span><span class="token class-name">ExpandoObject</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    List<span class="token operator">&lt;</span>PropertyInfo<span class="token operator">&gt;</span> propertyInfoList <span class="token operator">=</span> <span class="token keyword">typeof</span><span class="token punctuation">(</span>T<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">GetProeprties</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">foreach</span><span class="token punctuation">(</span><span class="token class-name">T</span> x <span class="token keyword">in</span> source<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    expandoObejctList<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>x<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>propertyInfoList<span class="token punctuation">,</span> fields<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> expandoObejctList<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    ApiStudy.Infrastructure.Services.TypeHelperServices
    namespace ApiStudy.Infrastructure.Services

    {

    using System.Reflection;
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TypeHelperServices</span> <span class="token punctuation">:</span> <span class="token class-name">ITypeHelperServices</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">bool</span> <span class="token generic-method"><span class="token function">HasProperties</span><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token keyword">string</span> fields<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">true</span><span class="token punctuation">;</span> <span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> splitFields <span class="token operator">=</span> fields<span class="token punctuation">.</span><span class="token function">Split</span><span class="token punctuation">(</span><span class="token string">&apos;,&apos;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">foreach</span><span class="token punctuation">(</span><span class="token keyword">string</span> splitField <span class="token keyword">in</span> splitFields<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">string</span> proeprtyName <span class="token operator">=</span> splitField<span class="token punctuation">.</span><span class="token function">Trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">PropertyInfo</span> propertyInfo <span class="token operator">=</span> <span class="token keyword">typeof</span><span class="token punctuation">(</span>T<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">GetProperty</span><span class="token punctuation">(</span>
    proeprtyName<span class="token punctuation">,</span> BindingFlags<span class="token punctuation">.</span>Public <span class="token operator">|</span> BindingFlags<span class="token punctuation">.</span>Instance <span class="token operator">|</span> BindingFlags<span class="token punctuation">.</span>IgnoreCase<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>propertyInfo <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    UserContext.GetAllApiUsers(), UserContext.Get()
    [HttpGet(Name = "GetAllApiUsers")]

    public async Task<IActionResult> GetAllApiUsers(ApiUserParameters parameters)

    {

    //added code

    if (!_typeHelper.HasProperties<ApiUserResource>(parameters.Fields))

    return BadRequest("fields not exist.");
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>_propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ValidateMappingExistsFor</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token string">&quot;can&apos;t find fields for sorting.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> PaginatedList<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> apiUsers <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetAllApiUsersAsync</span><span class="token punctuation">(</span>parameters<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> sortedApiUserResources <span class="token operator">=</span>
    apiUserResources<span class="token punctuation">.</span><span class="token function">AsQueryable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ApplySort</span><span class="token punctuation">(</span>
    parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">,</span> _propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//modified code</span>
    IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> sharpedApiUserResources <span class="token operator">=</span>
    sortedApiUserResources<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>Fields<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> meta <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    apiUsers<span class="token punctuation">.</span>PageIndex<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageSize<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageCount<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>TotalItemsCount<span class="token punctuation">,</span>
    PreviousPageUrl <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>HasPreviousPage <span class="token punctuation">?</span> <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>PreviousPage<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">,</span>
    NextPageUrl <span class="token operator">=</span> apiUsers<span class="token punctuation">.</span>HasNextPage <span class="token punctuation">?</span> <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>NextPage<span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
    Response<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token string">&quot;X-Pagination&quot;</span><span class="token punctuation">,</span>
    JsonConvert<span class="token punctuation">.</span><span class="token function">SerializeObject</span><span class="token punctuation">(</span>
    meta<span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">JsonSerializerSettings</span>
    <span class="token punctuation">{</span> ContractResolver <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CamelCasePropertyNamesContractResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//modified code</span>
    <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>sharpedApiUserResources<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    配置返回的json名称风格为CamelCase

    StartupDevelopment.ConfigureServices
    services.AddMvc(options =>

    {

    options.ReturnHttpNotAcceptable = true;

    options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());

    })

    .AddJsonOptions(options =>

    {

    //added code

    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

    });

    HATEOAS

        <p>REST里最复杂的约束,构建成熟RESTAPI的核心
    </p>
    <ul>
    <li>可进化性,自我描述</li>
    <li>超媒体(Hypermedia,例如超链接)驱动如何消<br>
    费和使用API</li>
    </ul>
    <details>
    <summary>UserContext</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">private</span> IEnumerable<span class="token operator">&lt;</span>LinkResource<span class="token operator">&gt;</span> <span class="token function">CreateLinksForApiUser</span><span class="token punctuation">(</span><span class="token keyword">string</span> guid<span class="token punctuation">,</span><span class="token keyword">string</span> fields <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>

    {

    List<LinkResource> linkResources = new List<LinkResource>();

    if (string.IsNullOrEmpty(fields))

    {

    linkResources.Add(

    new LinkResource(Url.Link("GetApiUser", new { guid }), "self", "get"));

    }

    else

    {

    linkResources.Add(

    new LinkResource(Url.Link("GetApiUser", new { guid, fields }), "self", "get"));

    }

    linkResources<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token keyword">new</span> <span class="token class-name">LinkResource</span><span class="token punctuation">(</span>Url<span class="token punctuation">.</span><span class="token function">Link</span><span class="token punctuation">(</span><span class="token string">&quot;DeleteApiUser&quot;</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token punctuation">{</span> guid <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">&quot;self&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Get&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> linkResources<span class="token punctuation">;</span>

    }

    private IEnumerable<LinkResource> CreateLinksForApiUsers(ApiUserParameters parameters,bool hasPrevious,bool hasNext)

    {

    List<LinkResource> resources = new List<LinkResource>();

    resources<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token keyword">new</span> <span class="token class-name">LinkResource</span><span class="token punctuation">(</span>
    <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span>ResourceUriType<span class="token punctuation">.</span>CurrentPage<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token string">&quot;current_page&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;get&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>hasPrevious<span class="token punctuation">)</span>
    resources<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token keyword">new</span> <span class="token class-name">LinkResource</span><span class="token punctuation">(</span>
    <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>PreviousPage<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token string">&quot;previous_page&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;get&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>hasNext<span class="token punctuation">)</span>
    resources<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token keyword">new</span> <span class="token class-name">LinkResource</span><span class="token punctuation">(</span>
    <span class="token function">CreateApiUserUrl</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> ResourceUriType<span class="token punctuation">.</span>NextPage<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token string">&quot;next_page&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;get&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> resources<span class="token punctuation">;</span>

    }

    [HttpGet(Name = "GetAllApiUsers")]

    public async Task<IActionResult> GetAllApiUsers(ApiUserParameters parameters)

    {

    if (!_typeHelper.HasProperties<ApiUserResource>(parameters.Fields))

    return BadRequest("fields not exist.");

    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>_propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ValidateMappingExistsFor</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token string">&quot;can&apos;t find fields for sorting.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> PaginatedList<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> apiUsers <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetAllApiUsersAsync</span><span class="token punctuation">(</span>parameters<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> sortedApiUserResources <span class="token operator">=</span>
    apiUserResources<span class="token punctuation">.</span><span class="token function">AsQueryable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ApplySort</span><span class="token punctuation">(</span>
    parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">,</span> _propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> shapedApiUserResources <span class="token operator">=</span>
    sortedApiUserResources<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>Fields<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> shapedApiUserResourcesWithLinks <span class="token operator">=</span> shapedApiUserResources<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>
    x <span class="token operator">=&gt;</span>
    <span class="token punctuation">{</span>
    IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span> dict <span class="token operator">=</span> x <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>dict<span class="token punctuation">.</span>Keys<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;guid&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    dict<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;links&quot;</span><span class="token punctuation">,</span> <span class="token function">CreateLinksForApiUser</span><span class="token punctuation">(</span>dict<span class="token punctuation">[</span><span class="token string">&quot;guid&quot;</span><span class="token punctuation">]</span> <span class="token keyword">as</span> <span class="token keyword">string</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> dict <span class="token keyword">as</span> ExpandoObject<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">value</span> <span class="token operator">=</span> shapedApiUserResourcesWithLinks<span class="token punctuation">,</span>
    links <span class="token operator">=</span> <span class="token function">CreateLinksForApiUsers</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> apiUsers<span class="token punctuation">.</span>HasPreviousPage<span class="token punctuation">,</span> apiUsers<span class="token punctuation">.</span>HasNextPage<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">var</span> meta <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    apiUsers<span class="token punctuation">.</span>PageIndex<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageSize<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageCount<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>TotalItemsCount<span class="token punctuation">,</span>
    <span class="token comment">//PreviousPageUrl = apiUsers.HasPreviousPage ? CreateApiUserUrl(parameters, ResourceUriType.PreviousPage) : string.Empty,</span>
    <span class="token comment">//NextPageUrl = apiUsers.HasNextPage ? CreateApiUserUrl(parameters, ResourceUriType.NextPage) : string.Empty,</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
    Response<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token string">&quot;X-Pagination&quot;</span><span class="token punctuation">,</span>
    JsonConvert<span class="token punctuation">.</span><span class="token function">SerializeObject</span><span class="token punctuation">(</span>
    meta<span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">JsonSerializerSettings</span>
    <span class="token punctuation">{</span> ContractResolver <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CamelCasePropertyNamesContractResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    创建供应商特定媒体类型

        <ul>
    <li>application/vnd.mycompany.hateoas+json
    <ul>
    <li>vnd是vendor的缩写,这一条是mime
    type的原则,表示这个媒体类型是供应商特定的
    </li>
    <li>自定义的标识,也可能还包括额外的值,这里我是用的是公司名,随后是hateoas表示返回的响应里面要<br>
    包含链接</li>
    <li>“+json”</li>
    </ul>
    </li>
    <li>在Startup里注册.</li>
    </ul>
    <h4 class="mume-header" id="%E5%88%A4%E6%96%ADmedia-type%E7%B1%BB%E5%9E%8B">判断Media
    Type类型</h4> <ul>
    <li>[FromHeader(Name = &quot;Accept&quot;)] stringmediaType</li>
    </ul>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token comment">//Startup.ConfigureServices 中注册媒体类型</span>

    services.AddMvc(options =>

    {

    options.ReturnHttpNotAcceptable = true;

    //options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());

    JsonOutputFormatter formatter = options.OutputFormatters.OfType<JsonOutputFormatter>().FirstOrDefault();

    formatter.SupportedMediaTypes.Add("application/vnd.laggage.hateoas+json");

    })

    // get方法中判断媒体类型

    if (mediaType "application/json")

    return Ok(shapedApiUserResources);

    else if (mediaType "application/vnd.laggage.hateoas+json")

    {

    ...

    return;

    }

    注意,要是的 Action 认识 application/vnd.laggage.hateoss+json

    ,需要在Startup.ConfigureServices中注册这个媒体类型,上面的代码给出了具体操作.

    UserContext
    [HttpGet(Name = "GetAllApiUsers")]

    public async Task<IActionResult> GetAllApiUsers(ApiUserParameters parameters,[FromHeader(Name = "Accept")] string mediaType)

    {

    if (!_typeHelper.HasProperties<ApiUserResource>(parameters.Fields))

    return BadRequest("fields not exist.");
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>_propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ValidateMappingExistsFor</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token string">&quot;can&apos;t find fields for sorting.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> PaginatedList<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> apiUsers <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetAllApiUsersAsync</span><span class="token punctuation">(</span>parameters<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> sortedApiUserResources <span class="token operator">=</span>
    apiUserResources<span class="token punctuation">.</span><span class="token function">AsQueryable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ApplySort</span><span class="token punctuation">(</span>
    parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">,</span> _propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> shapedApiUserResources <span class="token operator">=</span>
    sortedApiUserResources<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>Fields<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>mediaType <span class="token operator">==</span> <span class="token string">&quot;application/json&quot;</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>shapedApiUserResources<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>mediaType <span class="token operator">==</span> <span class="token string">&quot;application/vnd.laggage.hateoas+json&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> shapedApiUserResourcesWithLinks <span class="token operator">=</span> shapedApiUserResources<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>
    x <span class="token operator">=&gt;</span>
    <span class="token punctuation">{</span>
    IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span> dict <span class="token operator">=</span> x <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>dict<span class="token punctuation">.</span>Keys<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;guid&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    dict<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;links&quot;</span><span class="token punctuation">,</span> <span class="token function">CreateLinksForApiUser</span><span class="token punctuation">(</span>
    dict<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>
    a <span class="token operator">=&gt;</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>
    a<span class="token punctuation">.</span>Key<span class="token punctuation">,</span><span class="token string">&quot;guid&quot;</span><span class="token punctuation">,</span>StringComparison<span class="token punctuation">.</span>OrdinalIgnoreCase<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> dict <span class="token keyword">as</span> ExpandoObject<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">value</span> <span class="token operator">=</span> shapedApiUserResourcesWithLinks<span class="token punctuation">,</span>
    links <span class="token operator">=</span> <span class="token function">CreateLinksForApiUsers</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> apiUsers<span class="token punctuation">.</span>HasPreviousPage<span class="token punctuation">,</span> apiUsers<span class="token punctuation">.</span>HasNextPage<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">var</span> meta <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    apiUsers<span class="token punctuation">.</span>PageIndex<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageSize<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageCount<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>TotalItemsCount<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
    Response<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token string">&quot;X-Pagination&quot;</span><span class="token punctuation">,</span>
    JsonConvert<span class="token punctuation">.</span><span class="token function">SerializeObject</span><span class="token punctuation">(</span>
    meta<span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">JsonSerializerSettings</span>
    <span class="token punctuation">{</span> ContractResolver <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CamelCasePropertyNamesContractResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span>$<span class="token string">&quot;Can&apos;t find resources for the given media type: [{mediaType}].&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    [HttpGet("{guid}",Name = "GetApiUser")]

    public async Task<IActionResult> Get(string guid, [FromHeader(Name = "Accept")] string mediaType , string fields = null)

    {

    if (!_typeHelper.HasProperties<ApiUserResource>(fields))

    return BadRequest("fields not exist.");

    <span class="token class-name">ApiUser</span> apiUser <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetApiUserByGuidAsync</span><span class="token punctuation">(</span>Guid<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>guid<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token keyword">if</span> <span class="token punctuation">(</span>apiUser <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">ApiUserResource</span> apiUserResource <span class="token operator">=</span> _mapper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Map</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">,</span> <span class="token class-name">ApiUserResource</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>apiUser<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">ExpandoObject</span> shapedApiUserResource <span class="token operator">=</span> apiUserResource<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mediaType <span class="token operator">==</span> <span class="token string">&quot;application/json&quot;</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>shapedApiUserResource<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>mediaType <span class="token operator">==</span> <span class="token string">&quot;application/vnd.laggage.hateoas+json&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span> shapedApiUserResourceWithLink <span class="token operator">=</span> shapedApiUserResource <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
    shapedApiUserResourceWithLink<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;links&quot;</span><span class="token punctuation">,</span> <span class="token function">CreateLinksForApiUser</span><span class="token punctuation">(</span>guid<span class="token punctuation">,</span> fields<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>shapedApiUserResourceWithLink<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token string">@&quot;Can&apos;t find resource for the given media type: [{mediaType}].&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    • 自定义Action约束.

    RequestHeaderMatchingMediaTypeAttribute
    [AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = true)]

    public class RequestHeaderMatchingMediaTypeAttribute : Attribute, IActionConstraint

    {

    private readonly string _requestHeaderToMatch;

    private readonly string[] _mediaTypes;
    <span class="token keyword">public</span> <span class="token function">RequestHeaderMatchingMediaTypeAttribute</span><span class="token punctuation">(</span><span class="token keyword">string</span> requestHeaderToMatch<span class="token punctuation">,</span> <span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> mediaTypes<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    _requestHeaderToMatch <span class="token operator">=</span> requestHeaderToMatch<span class="token punctuation">;</span>
    _mediaTypes <span class="token operator">=</span> mediaTypes<span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">bool</span> <span class="token function">Accept</span><span class="token punctuation">(</span><span class="token class-name">ActionConstraintContext</span> context<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">var</span> requestHeaders <span class="token operator">=</span> context<span class="token punctuation">.</span>RouteContext<span class="token punctuation">.</span>HttpContext<span class="token punctuation">.</span>Request<span class="token punctuation">.</span>Headers<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>requestHeaders<span class="token punctuation">.</span><span class="token function">ContainsKey</span><span class="token punctuation">(</span>_requestHeaderToMatch<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token keyword">var</span> mediaType <span class="token keyword">in</span> _mediaTypes<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">var</span> mediaTypeMatches <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>requestHeaders<span class="token punctuation">[</span>_requestHeaderToMatch<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    mediaType<span class="token punctuation">,</span> StringComparison<span class="token punctuation">.</span>OrdinalIgnoreCase<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mediaTypeMatches<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token keyword">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">int</span> Order <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

    }

    UserContext
    [HttpGet(Name = "GetAllApiUsers")]

    [RequestHeaderMatchingMediaType("Accept",new string[] { "application/vnd.laggage.hateoas+json" })]

    public async Task<IActionResult> GetHateoas(ApiUserParameters parameters)

    {

    if (!_typeHelper.HasProperties<ApiUserResource>(parameters.Fields))

    return BadRequest("fields not exist.");
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>_propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ValidateMappingExistsFor</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token string">&quot;can&apos;t find fields for sorting.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> PaginatedList<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> apiUsers <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetAllApiUsersAsync</span><span class="token punctuation">(</span>parameters<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> sortedApiUserResources <span class="token operator">=</span>
    apiUserResources<span class="token punctuation">.</span><span class="token function">AsQueryable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ApplySort</span><span class="token punctuation">(</span>
    parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">,</span> _propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> shapedApiUserResources <span class="token operator">=</span>
    sortedApiUserResources<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>Fields<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> shapedApiUserResourcesWithLinks <span class="token operator">=</span> shapedApiUserResources<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>
    x <span class="token operator">=&gt;</span>
    <span class="token punctuation">{</span>
    IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span> dict <span class="token operator">=</span> x <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>dict<span class="token punctuation">.</span>Keys<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">&quot;guid&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    dict<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;links&quot;</span><span class="token punctuation">,</span> <span class="token function">CreateLinksForApiUser</span><span class="token punctuation">(</span>
    dict<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>
    a <span class="token operator">=&gt;</span> <span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">Equals</span><span class="token punctuation">(</span>
    a<span class="token punctuation">.</span>Key<span class="token punctuation">,</span><span class="token string">&quot;guid&quot;</span><span class="token punctuation">,</span>StringComparison<span class="token punctuation">.</span>OrdinalIgnoreCase<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span>Value<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> dict <span class="token keyword">as</span> ExpandoObject<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">value</span> <span class="token operator">=</span> shapedApiUserResourcesWithLinks<span class="token punctuation">,</span>
    links <span class="token operator">=</span> <span class="token function">CreateLinksForApiUsers</span><span class="token punctuation">(</span>parameters<span class="token punctuation">,</span> apiUsers<span class="token punctuation">.</span>HasPreviousPage<span class="token punctuation">,</span> apiUsers<span class="token punctuation">.</span>HasNextPage<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">var</span> meta <span class="token operator">=</span> <span class="token keyword">new</span>
    <span class="token punctuation">{</span>
    apiUsers<span class="token punctuation">.</span>PageIndex<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageSize<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>PageCount<span class="token punctuation">,</span>
    apiUsers<span class="token punctuation">.</span>TotalItemsCount<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
    Response<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>
    <span class="token string">&quot;X-Pagination&quot;</span><span class="token punctuation">,</span>
    JsonConvert<span class="token punctuation">.</span><span class="token function">SerializeObject</span><span class="token punctuation">(</span>
    meta<span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">JsonSerializerSettings</span>
    <span class="token punctuation">{</span> ContractResolver <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CamelCasePropertyNamesContractResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    [HttpGet(Name = "GetAllApiUsers")]

    [RequestHeaderMatchingMediaType("Accept",new string[] { "application/json" })]

    public async Task<IActionResult> Get(ApiUserParameters parameters)

    {

    if (!_typeHelper.HasProperties<ApiUserResource>(parameters.Fields))

    return BadRequest("fields not exist.");

    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>_propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">ValidateMappingExistsFor</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token function">BadRequest</span><span class="token punctuation">(</span><span class="token string">&quot;can&apos;t find fields for sorting.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> PaginatedList<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span> apiUsers <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetAllApiUsersAsync</span><span class="token punctuation">(</span>parameters<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> apiUserResources <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span>Map<span class="token operator">&lt;</span>IEnumerable<span class="token operator">&lt;</span>ApiUser<span class="token operator">&gt;</span><span class="token punctuation">,</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>apiUsers<span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ApiUserResource<span class="token operator">&gt;</span> sortedApiUserResources <span class="token operator">=</span>
    apiUserResources<span class="token punctuation">.</span><span class="token function">AsQueryable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ApplySort</span><span class="token punctuation">(</span>
    parameters<span class="token punctuation">.</span>OrderBy<span class="token punctuation">,</span> _propertyMappingContainer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Resolve</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">,</span> <span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> IEnumerable<span class="token operator">&lt;</span>ExpandoObject<span class="token operator">&gt;</span> shapedApiUserResources <span class="token operator">=</span>
    sortedApiUserResources<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>parameters<span class="token punctuation">.</span>Fields<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>shapedApiUserResources<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    [HttpGet("{guid}", Name = "GetApiUser")]

    [RequestHeaderMatchingMediaType("Accept", new string[] { "application/vnd.laggage.hateoas+json" })]

    public async Task<IActionResult> GetHateoas(string guid, string fields = null)

    {

    if (!_typeHelper.HasProperties<ApiUserResource>(fields))

    return BadRequest("fields not exist.");

    <span class="token class-name">ApiUser</span> apiUser <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetApiUserByGuidAsync</span><span class="token punctuation">(</span>Guid<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>guid<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token keyword">if</span> <span class="token punctuation">(</span>apiUser <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">ApiUserResource</span> apiUserResource <span class="token operator">=</span> _mapper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Map</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">,</span> <span class="token class-name">ApiUserResource</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>apiUser<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">ExpandoObject</span> shapedApiUserResource <span class="token operator">=</span> apiUserResource<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">;</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span> shapedApiUserResourceWithLink <span class="token operator">=</span> shapedApiUserResource <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
    shapedApiUserResourceWithLink<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;links&quot;</span><span class="token punctuation">,</span> <span class="token function">CreateLinksForApiUser</span><span class="token punctuation">(</span>guid<span class="token punctuation">,</span> fields<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>shapedApiUserResourceWithLink<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    [HttpGet("{guid}", Name = "GetApiUser")]

    [RequestHeaderMatchingMediaType("Accept", new string[] { "application/json" })]

    public async Task<IActionResult> Get(string guid, string fields = null)

    {

    if (!_typeHelper.HasProperties<ApiUserResource>(fields))

    return BadRequest("fields not exist.");

    <span class="token class-name">ApiUser</span> apiUser <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetApiUserByGuidAsync</span><span class="token punctuation">(</span>Guid<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>guid<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token keyword">if</span> <span class="token punctuation">(</span>apiUser <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">ApiUserResource</span> apiUserResource <span class="token operator">=</span> _mapper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Map</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">,</span> <span class="token class-name">ApiUserResource</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>apiUser<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">ExpandoObject</span> shapedApiUserResource <span class="token operator">=</span> apiUserResource<span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">Ok</span><span class="token punctuation">(</span>shapedApiUserResource<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    Post添加资源

        <p>Post - <strong>不安全</strong>,<strong>非幂等</strong><br>
    要返回添加好的资源,并且返回头中有获得新创建资源的连接.
    </p>
    <h3 class="mume-header" id="%E5%AE%89%E5%85%A8%E6%80%A7%E5%92%8C%E5%B9%82%E7%AD%89%E6%80%A7">
    安全性和幂等性</h3> <ul>
    <li>安全性是指方法执行后并不会改变资源的表述
    </li>
    <li>幂等性是指方法无论执行多少次都会得到同样<br>
    的结果<br>
    <img src="https://img2018.cnblogs.com/blog/1596066/201907/1596066-20190703115335902-2000181175.png" alt>
    </li>
    </ul>
    <h3 class="mume-header" id="%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0">代码实现</h3> <p>StartUp中注册Fluent,用于验证</p>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp">services<span class="token punctuation">.</span><span class="token function">AddMvc</span><span class="token punctuation">(</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">AddFluentValidation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    services.AddTransient<IValidator<ApiUserAddResource>, ApiUserAddResourceValidator>();

    ApiStudy.Infrastructure.Resources.ApiUserAddResourceValidator
    namespace ApiStudy.Infrastructure.Resources

    {

    using FluentValidation;
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ApiUserAddResourceValidator</span> <span class="token punctuation">:</span> <span class="token class-name">AbstractValidator</span><span class="token operator">&lt;</span>ApiUserAddResource<span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token function">ApiUserAddResourceValidator</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token function">RuleFor</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">MaximumLength</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">&quot;用户名&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}的最大长度为20!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}是必填的!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}不能为空!&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">RuleFor</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span>Passwd<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">&quot;密码&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}是必填的!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">MinimumLength</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}的最小长度是6&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">MaximumLength</span><span class="token punctuation">(</span><span class="token number">16</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}的最大长度是16&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">RuleFor</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span>PhoneNumber<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">&quot;电话&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}是必填的!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}不能为空!&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    UserContext.AddApiUser()
    [HttpPost(Name = "CreateApiUser")]

    [RequestHeaderMatchingMediaType("Content-Type",new string[] { "application/vnd.laggage.create.apiuser+json" })]

    [RequestHeaderMatchingMediaType("Accept",new string[] { "application/vnd.laggage.hateoas+json" })]

    public async Task<IActionResult> AddUser([FromBody] ApiUserAddResource apiUser)

    {

    if (!ModelState.IsValid)

    return UnprocessableEntity(ModelState);
    <span class="token class-name">ApiUser</span> newUser <span class="token operator">=</span> _mapper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Map</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUser</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>apiUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
    newUser<span class="token punctuation">.</span>Guid <span class="token operator">=</span> Guid<span class="token punctuation">.</span><span class="token function">NewGuid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    newUser<span class="token punctuation">.</span>ProfilePhotoUrl <span class="token operator">=</span> $<span class="token string">&quot;www.eample.com/photo/{newUser.Guid}&quot;</span><span class="token punctuation">;</span>
    newUser<span class="token punctuation">.</span>RegistrationDate <span class="token operator">=</span> DateTime<span class="token punctuation">.</span>Now<span class="token punctuation">;</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">AddApiUserAsync</span><span class="token punctuation">(</span>newUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">await</span> _unitOfWork<span class="token punctuation">.</span><span class="token function">SaveChangesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Exception</span><span class="token punctuation">(</span><span class="token string">&quot;Failed to save changes&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span> shapedUserResource <span class="token operator">=</span>
    _mapper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Map</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserResource</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>newUser<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">ToDynamicObject</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> IDictionary<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
    IEnumerable<span class="token operator">&lt;</span>LinkResource<span class="token operator">&gt;</span> links <span class="token operator">=</span> <span class="token function">CreateLinksForApiUser</span><span class="token punctuation">(</span>newUser<span class="token punctuation">.</span>Guid<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    shapedUserResource<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;links&quot;</span><span class="token punctuation">,</span> links<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">CreatedAtRoute</span><span class="token punctuation">(</span><span class="token string">&quot;GetApiUser&quot;</span><span class="token punctuation">,</span><span class="token keyword">new</span> <span class="token punctuation">{</span> newUser<span class="token punctuation">.</span>Guid <span class="token punctuation">}</span><span class="token punctuation">,</span> shapedUserResource<span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    Delete

        <ul>
    <li>参数 : <strong>ID</strong></li>
    <li>幂等的
    <ul>
    <li>多次请求的副作用和单次请求的副作用是一样的.每次发送了DELETE请求之后,服务器的状态都是一样的.
    </li>
    </ul>
    </li>
    <li>不安全</li>
    </ul>
    <details>
    <summary>ApiStudy.Api.Controllers.UserController</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token punctuation">[</span><span class="token class-name">HttpDelete</span><span class="token punctuation">(</span><span class="token string">&quot;{guid}&quot;</span><span class="token punctuation">,</span>Name <span class="token operator">=</span> <span class="token string">&quot;DeleteApiUser&quot;</span><span class="token punctuation">)</span><span class="token punctuation">]</span>

    public async Task<IActionResult> DeleteApiUser(string guid)

    {

    ApiUser userToDelete = await _apiUserRepository.GetApiUserByGuidAsync(new Guid(guid));

    <span class="token keyword">if</span> <span class="token punctuation">(</span>userToDelete <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    
    <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">DeleteApiUserAsync</span><span class="token punctuation">(</span>userToDelete<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">await</span> _unitOfWork<span class="token punctuation">.</span><span class="token function">SaveChangesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Exception</span><span class="token punctuation">(</span><span class="token string">&quot;Failed to delete apiUser&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">NoContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    PUT & PATCH

        <p>相关类:</p>
    <details>
    <summary>ApiStudy.Infrastructure.Resources.ApiUserAddOrUpdateResource</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token keyword">namespace</span> ApiStudy<span class="token punctuation">.</span>Infrastructure<span class="token punctuation">.</span>Resources

    {

    using System;

    <span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">ApiUserAddOrUpdateResource</span>
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Name <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Passwd <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token class-name">DateTime</span> Birth <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> PhoneNumber <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">string</span> Email <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    ApiStudy.Infrastructure.Resources.ApiUserAddResource
    namespace ApiStudy.Infrastructure.Resources

    {

    public class ApiUserAddResource:ApiUserAddOrUpdateResource

    {

    }

    }

    ApiStudy.Infrastructure.Resources.ApiUserUpdateResource
    namespace ApiStudy.Infrastructure.Resources

    {

    public class ApiUserUpdateResource : ApiUserAddOrUpdateResource

    {

    }

    }

    ApiStudy.Infrastructure.Resources.ApiUserAddOrUpdateResourceValidator
    namespace ApiStudy.Infrastructure.Resources

    {

    using FluentValidation;
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ApiUserAddOrUpdateResourceValidator</span><span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token punctuation">:</span> AbstractValidator<span class="token operator">&lt;</span>T<span class="token operator">&gt;</span> <span class="token keyword">where</span> T<span class="token punctuation">:</span> ApiUserAddOrUpdateResource
    <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token function">ApiUserAddOrUpdateResourceValidator</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token function">RuleFor</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">MaximumLength</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">&quot;用户名&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}的最大长度为20!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}是必填的!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}不能为空!&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">RuleFor</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span>Passwd<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">&quot;密码&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}是必填的!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">MinimumLength</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}的最小长度是6&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">MaximumLength</span><span class="token punctuation">(</span><span class="token number">16</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}的最大长度是16&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">RuleFor</span><span class="token punctuation">(</span>x <span class="token operator">=&gt;</span> x<span class="token punctuation">.</span>PhoneNumber<span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotNull</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithName</span><span class="token punctuation">(</span><span class="token string">&quot;电话&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}是必填的!&quot;</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">NotEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span><span class="token string">&quot;{PropertyName}不能为空!&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    }

    PUT 整体更新

        <ul>
    <li>返回204</li>
    <li>参数
    <ul>
    <li>ID,</li>
    <li>[FromBody]XxxxUpdateResource</li>
    </ul>
    </li>
    </ul>
    <details>
    <summary>ApiStudy.Api.Controllers.UpdateApiUser</summary>
    <pre data-role="codeBlock" data-info="CSharp" class="language-csharp"><span class="token punctuation">[</span><span class="token class-name">HttpPut</span><span class="token punctuation">(</span><span class="token string">&quot;{guid}&quot;</span><span class="token punctuation">,</span>Name <span class="token operator">=</span> <span class="token string">&quot;PutApiUser&quot;</span><span class="token punctuation">)</span><span class="token punctuation">]</span>

    public async Task<IActionResult> UpdateApiUser(string guid,[FromBody] ApiUserUpdateResource apiUserUpdateResource)

    {

    if (!ModelState.IsValid) return BadRequest(ModelState);

    <span class="token class-name">ApiUser</span> userToUpdate <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetApiUserByGuidAsync</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Guid</span><span class="token punctuation">(</span>guid<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>userToUpdate <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> _mapper<span class="token punctuation">.</span><span class="token function">Map</span><span class="token punctuation">(</span>apiUserUpdateResource<span class="token punctuation">,</span> userToUpdate<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">await</span> _unitOfWork<span class="token punctuation">.</span><span class="token function">SaveChangesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Exception</span><span class="token punctuation">(</span><span class="token string">&quot;Failed to update Entity of ApiUser&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">NoContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    PATCH

        <ul>
    <li>Content-Type
    <ul>
    <li>application/json-patch+json</li>
    </ul>
    </li>
    <li>返回204</li>
    <li>参数
    <ul>
    <li>ID</li>
    <li>[FromBody] JsonPatchDocument<xxxxupdateresource></xxxxupdateresource>
    </li>
    </ul>
    </li>
    <li>op操作
    <ul>
    <li>添加:{“op”: &quot;add&quot;, &quot;path&quot;:
    &quot;/xxx&quot;, &quot;value&quot;:
    &quot;xxx&quot;},如果该属性不存,那么就添加该属性,如<br>
    果属性存在,就改变属性的值。这个对静态类型不适用。
    </li>
    <li>删除:{“op”: &quot;<strong>remove</strong>&quot;,
    &quot;path&quot;:
    &quot;/xxx&quot;},删除某个属性,或把它设为默认值(例如空值)。
    </li>
    <li>替换:{“op”: &quot;<strong>replace</strong>&quot;,
    &quot;path&quot;: &quot;/xxx&quot;, &quot;value&quot;:
    &quot;xxx&quot;},改变属性的值,也可以理解为先执行<br>
    了删除,然后进行添加。</li>
    <li>复制:{“op”: &quot;copy&quot;, &quot;from&quot;:
    &quot;/xxx&quot;, &quot;path&quot;:
    &quot;/yyy&quot;},把某个属性的值赋给目标属性。
    </li>
    <li>移动:{“op”: &quot;move&quot;, &quot;from&quot;:
    &quot;/xxx&quot;, &quot;path&quot;:
    &quot;/yyy&quot;},把源属性的值赋值给目标属性,并把源<br>
    属性删除或设成默认值。</li>
    <li>测试:{“op”: &quot;test&quot;, &quot;path&quot;:
    &quot;/xxx&quot;, &quot;value&quot;:
    &quot;xxx&quot;},测试目标属性的值和指定的值是一样的。
    </li>
    </ul>
    </li>
    <li><strong>path,资源的属性名</strong>
    <ul>
    <li>可以有层级结构</li>
    </ul>
    </li>
    <li><strong>value 更新的值</strong></li>
    </ul>
    <pre data-role="codeBlock" data-info="json" class="language-json"><span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
    <span class="token property">&quot;op&quot;</span><span class="token operator">:</span><span class="token string">&quot;replace&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;path&quot;</span><span class="token operator">:</span><span class="token string">&quot;/name&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;value&quot;</span><span class="token operator">:</span><span class="token string">&quot;阿黄&quot;</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
    <span class="token property">&quot;op&quot;</span><span class="token operator">:</span><span class="token string">&quot;remove&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;path&quot;</span><span class="token operator">:</span><span class="token string">&quot;/email&quot;</span>
    <span class="token punctuation">}</span>

    ]

    ApiStudy.Api.Controllers.UserContext.UpdateApiUser
    [HttpPatch("{guid}",Name = "PatchApiUser")]

    [RequestHeaderMatchingMediaType("Content-Type",new string[] { "application/vnd.laggage.patch.apiuser+json" })]

    public async Task<IActionResult> UpdateApiUser(

    string guid,[FromBody] JsonPatchDocument<ApiUserUpdateResource> userUpdateDoc)

    {

    if (userUpdateDoc == null) return BadRequest();
    <span class="token class-name">ApiUser</span> userToUpdate <span class="token operator">=</span> <span class="token keyword">await</span> _apiUserRepository<span class="token punctuation">.</span><span class="token function">GetApiUserByGuidAsync</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Guid</span><span class="token punctuation">(</span>guid<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>userToUpdate <span class="token keyword">is</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">NotFound</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">ApiUserUpdateResource</span> userToUpdateResource <span class="token operator">=</span> _mapper<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Map</span><span class="token punctuation">&lt;</span><span class="token class-name">ApiUserUpdateResource</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>userToUpdate<span class="token punctuation">)</span><span class="token punctuation">;</span>
    userUpdateDoc<span class="token punctuation">.</span><span class="token function">ApplyTo</span><span class="token punctuation">(</span>userToUpdateResource<span class="token punctuation">)</span><span class="token punctuation">;</span> _mapper<span class="token punctuation">.</span><span class="token function">Map</span><span class="token punctuation">(</span>userToUpdateResource<span class="token punctuation">,</span> userToUpdate<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">await</span> _unitOfWork<span class="token punctuation">.</span><span class="token function">SaveChangesAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Exception</span><span class="token punctuation">(</span><span class="token string">&quot;Failed to update Entity of ApiUser&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">NoContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    }

    Http常用方法总结

        <ul>
    <li><strong>GET</strong>(获取资源):
    <ul>
    <li>GET
    api/countries,返回200,集合数据;找不到数据返回404。
    </li>
    <li>GET
    api/countries/{id},返回200,单个数据;找不到返回404.
    </li>
    </ul>
    </li>
    <li><strong>DELETE</strong>(删除资源)
    <ul>
    <li>DELETE
    api/countries/{id},成功204;没找到资源404。
    </li>
    <li>DELETE
    api/countries,很少用,也是204或者404.
    </li>
    </ul>
    </li>
    <li><strong>POST</strong> (创建资源):
    <ul>
    <li>POST
    api/countries,成功返回201和单个数据;如果资源没有创建则返回404
    </li>
    <li>POST
    api/countries/{id},肯定不会成功,返回404或409.
    </li>
    <li>POST
    api/countrycollections,成功返回201和集合;没创建资源则返回404
    </li>
    </ul>
    </li>
    <li><strong>PUT</strong> (整体更新):
    <ul>
    <li>PUT
    api/countries/{id},成功可以返回200,204;没找到资源则返回404
    </li>
    <li>PUT
    api/countries,集合操作很少见,返回200,204或404
    </li>
    </ul>
    </li>
    <li><strong>PATCH</strong>(局部更新):
    <ul>
    <li>PATCHapi/countries/{id},200单个数据,204或者404
    </li>
    <li>PATCHapi/countries,集合操作很少见,返回200集合,204或404.
    </li>
    </ul>
    </li>
    </ul> </div>

    Asp.NetCoreWebApi - RESTful Api的更多相关文章

    1. ASP.NET Core Web API 开发-RESTful API实现

      ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输(英文:Representa ...

    2. IIS 部署ASP.Net, WebAPI, Restful API, PUT/DELETE 报405错解决办法, webapi method not allowed 405

      WebDAV 是超文本传输协议 (HTTP) 的一组扩展,为 Internet 上计算机之间的编辑和文件管理提供了标准.利用这个协议用户可以通过Web进行远程的基本文件操作,如拷贝.移动.删除等.在I ...

    3. 使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作

      以前写过ASP.NET Core 2.x的REST API文章,今年再更新一下到3.0版本. 先决条件 我在B站有一个非常入门的ASP.NET Core 3.0的视频教程,如果您对ASP.NET Co ...

    4. 使用ASP.NET Core 3.x 构建 RESTful API - 2. 什么是RESTful API

      1. 使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作 什么是REST REST一词最早是在2000年,由Roy Fielding在他的博士论文<Archit ...

    5. 使用ASP.NET Core 3.x 构建 RESTful API - 3.4 内容协商

      现在,当谈论起 RESTful Web API 的时候,人们总会想到 JSON.但是实际上,JSON 和 RESTful API 没有半毛钱关系,只不过 JSON 恰好是RESTful API 结果的 ...

    6. 使用ASP.NET Core构建RESTful API的技术指南

      译者荐语:利用周末的时间,本人拜读了长沙.NET技术社区翻译的技术标准<微软RESTFul API指南>,打算按照步骤写一个完整的教程,后来无意中看到了这篇文章,与我要写的主题有不少相似之 ...

    7. 使用ASP.NET Core 3.x 构建 RESTful API - 3.1 资源命名

      之前讲了RESTful API的统一资源接口这个约束,里面提到了资源是通过URI来进行识别的,每个资源都有自己的URI.URI里还涉及到资源的名称,而针对资源的名称却没有一个标准来进行规范,但是业界还 ...

    8. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

      由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

    9. How ASP.NET Web API 2.0 Works?[持续更新中…]

      一.概述 RESTful Web API [Web标准篇]RESTful Web API [设计篇] 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 二.路由 ...

    随机推荐

    1. Docker 清理日志

      docker 长时间运行后,日志文件会逐渐变大可以使用下面命令进行清除 #!/bin/bash echo "==================== start clean docker c ...

    2. odoo10学习笔记四:onchange、唯一性约束

      转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/11189273.html 一:onchange机制[onchange=前端js函数!可以实现前端实时更新以及修 ...

    3. Python 简易web日志查看工具&可改装为命令行工具

      Python 简易web日志查看工具&可改装为命令行工具 效果图 原理 利用python的paramiko库模拟ssh登录操作,并执行tail命令 所需库 flask.paramiko.gev ...

    4. c# 第18节 数组的操作

      本节内容: 1:遍历数组 2:查找数组元素 3:数组排序 4:数组合并与拆分 5:数组的添加 1:遍历数组 遍历数组方法: :数组.length ###获取数组长度 :数组.GetLowerBound ...

    5. 201871010126 王亚涛 《面向对象程序设计(Java)》第八周实验总结

      项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

    6. docker 持久化存储

      1.data Volume  mysql5.7:dockerfile FROM debian:stretch-slim # add our user and group first to make s ...

    7. Springboot将数据存储到数据库当中

      1.从前端获取数据,同时存储到use当中 public String login(HttpServletRequest request) { User user = new User(); user. ...

    8. 【Oracle】Windows启动

      cd D:\app\Administrator\product\\dbhome_1\BIN D: sqlplus /nolog conn sys/system as sysdba startup pf ...

    9. python27期尚哥讲网络编程:

      python27day26网络编程----------------------------------------------------------------------------------- ...

    10. leetcode138. 复制带随机指针的链表

      思路一:哈希 借助哈希保存节点信息. 代码 时间复杂度:O(n)空间复杂度:O(n) class Solution{ public: Node* copyRandomList(Node* head) ...