目录

介绍

这种方法有什么好处?

Restful约定

构建API

测试API

一点困惑:

最佳实践:

数据传输对象(DTO)

Automapper

IHttpActionResult

使用Web API

结论


在本文中,我们将构建测试并使用asp.net web api。

介绍

让我们快速回顾一下ASP.NET MVC架构。因此,当请求到达我们的应用程序时,MVC Framework将该请求移交给控制器中的操作,此操作大部分时间返回一个视图,然后由razor视图引擎解析,最终将HTML标记返回给客户端。因此,在这种方法中,在服务器上生成html标记,然后返回到客户端。

有另一种生成HTML标记的方法,我们可以在客户端生成它。因此,不是我们的操作返回HTML标记,它们可以返回原始数据。

这种方法有什么好处?

在客户端上生成标记有很多好处。

  • 它需要更少的服务器资源(它潜在地提高了应用程序的可伸缩性,因为每个客户机将负责生成自己的视图)
  • 原始数据通常比HTML标记需要更少的带宽。因此,数据可能会更快到达客户端。这可以提高应用程序的感知性能。
  • 此方法支持广泛的客户端,如移动和平板电脑应用程序。

这些应用程序简称为端点获取数据并在本地生成视图。我们将这些端点称为数据服务(Web API),因为它们只返回数据,而不是标记。

Web API不仅限于交叉设备,它还广泛用于我们的Web应用程序中,以添加新功能,如youtube,facebook和twitter等许多热门网站,从而公开我们可以在我们的Web应用程序中使用的公共数据服务。我们可以将他们的数据与我们应用程序中的数据合并,并为新用户提供新的体验。这些都是好处。

这些数据服务不仅仅是为了获取数据,我们还提供修改数据的服务,例如添加客户等。我们用来构建这些数据服务的框架称为Web API。这个框架是在ASP.Net MVC之后开发的,但它遵循ASP.NET MVC的相同体系结构和原理,因此它具有路由,控制器,操作,操作结果等。我们在这里看到的细微差别也很少。在.Net Core中,Microsoft已将这两个框架(ASP.NET MVC和ASP.NET Web API)合并到一个框架中。

Restful约定

所以你知道什么是http服务,什么是web api。在这里,我们将开发一个支持几种不同类型请求的应用程序。

GET        / api / customers(获取客户列表)

GET       / api / customers / 1(获得单个客户)

POST     / api / customers(添加客户并在请求正文中添加客户数据)

不要混淆请求数据的GET和POST方式,我们使用get请求来获取资源或数据的列表。我们使用post请求来创建新的数据。

现在更新学生我们使用PUT请求。

PUT        / api / customers / 1

因此,客户的ID位于URL中,要更新的实际数据或属性将位于请求正文中。最后删除学生。

Delete     / api / customers / 1

我们将HttpDelete请求发送到端点。所以你在这里看到的,就请求类型和端点而言,是一个标准约定,被交付请求RESTRepresentational State Transfer

构建API

此类派生自ApiController,而不是Controller。如果您正在使用任何现有项目,则只需在controllers文件夹中添加一个新文件夹,并在此处添加api控制器。并添加这些操作,但在apis中定义操作之前,这是我的Customer模型类。

public class Customer
{public int Id { get; set; }[Required][StringLength(255)]public string Name { get; set; }public bool IsSubscribedToNewsLetter { get; set; }[Display(Name = "Date of Birth")]public DateTime? Birthdate { get; set; }[Display(Name = "Membership Type")]public byte MembershipTypeId { get; set; }// it allows us to navigate from 1 type to anotherpublic MembershipType MembershipType { get; set; }
}

这是我的DbContext类

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{public ApplicationDbContext():base("DefaultConnection", throwIfV1Schema: false){}public static ApplicationDbContext Create(){return new ApplicationDbContext();}public DbSet<Customer> Customers { get; set; }public DbSet<MembershipType> MembershipTypes { get; set; }
}

现在,您可以轻松地为Api编写操作。

public IEnumerable<Customer> GetCustomers()
{
}

因为我们正在返回一个对象列表。按约定,此操作将作出回应

//Get       / api / customers

所以这是ASP.Net Web API中内置的约定。现在,在这个操作中,我们将使用我们的上下文从数据库中获取客户。

namespace MyAPI.Controllers.Api
{public class CustomersController : ApiController{private readonly ApplicationDbContext _context;public CustomersController(){_context = new ApplicationDbContext();}// GET /api/customerspublic IEnumerable<Customer> GetCustomers(){return _context.Customers.ToList();}}
}

如果找不到资源,我们返回找不到httpresponse,否则我们返回该对象。

// POST /api/customers
[HttpPost]
public Customer CreateCustomer(Customer customer)
{
}

所以这是客户参数将在请求体中,ASP.NET Web API框架将自动初始化它。现在我们应该用HttpPost标记这个操作,因为我们正在创建资源。如果我们遵循命名约定,那么我们甚至不需要将操作动词放在操作上。

// POST /api/customers
public Customer PostCustomer(Customer customer)
{
}

但最初它不是那么好的方法,让我们假设您将来重构代码并重命名您的操作,那么您的代码肯定会破坏。所以总是喜欢在操作的顶部使用Http动词。

现在让我们使用api操作的post请求的将客户对象插入到数据库中。

// POST /api/customers
[HttpPost]
public Customer CreateCustomer(Customer customer)
{if (!ModelState.IsValid){throw new HttpResponseException(HttpStatusCode.BadRequest);}_context.Customers.Add(customer);_context.SaveChanges();return customer;
}

另一个操作让我们假设我们要更新记录。

// PUT /api/customers/1
[HttpPut]
public void UpdateCustomer(int id, Customer customer)
{if (!ModelState.IsValid){throw new HttpResponseException(HttpStatusCode.BadRequest);}var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);// Might be user sends invalid id.if (custmr == null){throw new HttpResponseException(HttpStatusCode.NotFound);}custmr.Birthdate = customer.Birthdate;custmr.IsSubscribedToNewsLetter = customer.IsSubscribedToNewsLetter;custmr.Name = customer.Name;custmr.MembershipTypeId = customer.MembershipTypeId;_context.SaveChanges();
}

在这种情况下,不同的人有不同的意见来返回void或对象。如果我们进行Api的删除操作。

// Delete /api/customers/1
[HttpDelete]
public void DeleteCustomer(int id)
{var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);// Might be user sends invalid id.if (custmr == null){throw new HttpResponseException(HttpStatusCode.NotFound);}_context.Customers.Remove(custmr);// Now the object is marked as removed in memory// Now it is done_context.SaveChanges();
}

这就是我们如何使用restful约定来构建api。

测试API

如果我们运行应用程序并请求api控制器,我们可以看到基于XML语言的客户列表。

<a href="http://localhost:53212/api/customers">http://localhost:53212/api/customers</a>

因此,ASP.NET Web API具有我们所谓的媒体格式化程序。因此,我们从一个动作中返回的内容(在我们的情况下,客户列表将根据客户要求进行格式化)让我解释一下我的意思和我想说的内容。

在上面的屏幕上检查浏览器并刷新页面,在这里您将看到客户请求。

这里查看内容类型,如果您在我们的请求中没有设置内容类型标头,则默认情况下服务器采用application / xml。

注意: General是请求标头,Response Headers是我们的响应标头。正如您在Request Header中看到的,我们没有任何内容类型。现在让我告诉你最好测试api的方式并返回json数据。

在您的计算机中安装Postman Desktop App。并使用localhost端口号复制浏览器链接并将其粘贴到postman。

在这里,我们将请求的url与localhost放在一起,而响应在json中返回。

如果我们点击Header选项卡,这里我们将看到我们的请求标头内容类型是application / json

大多数时候我们将使用json,因为它是javascript代码的原生代码,比xml快得多。XML媒体格式主要用于政府等大型组织,因为它们落后于现代技术。Json格式更轻量级,因为它没有像xml那样的多余的开启和关闭选项卡。

一点困惑:

有时当你使用Api或postman时,大多数人都会对Postman的界面感到困惑,因为他们之前从未使用过postman。记住这一点非常简单,

因此,如果您正在处理请求并尝试更改请求的某些信息,请关注请求标头,如果您正在监视响应,请在响应标头中查看结果。因为它们看起来相同,有时当请求标题的向下滚动消失时。所以不要混淆事情。

现在让我们使用Api Post 操作在数据库中插入一个客户。

从下拉列表和请求正文选项卡中选择Post请求。您可以在单击表单数据时插入具有键值对的客户。但大多数时候我们使用json格式。所以点击raw并在这里写json。

不要将Id属性放在json中,因为当我们在数据库中插入数据时,它是硬性规则,在服务器上自动生成id。

现在点击Send按钮,这里我已通过Post api操作成功插入数据并获得响应。

这里上面的块是请求块,下面的块是响应块。你可能会在这里遇到某种错误。

如果您阅读错误消息'此资源不支持请求实体的媒体类型'text / plain'。这是错误消息。

现在来解决这个错误。单击Header选项卡并添加content-type的值('application / json')

这里已经添加了值。查看请求的状态代码是200 OK,我们可以在下面看到响应正文。

现在让我们更新客户实体。

看看它已经更新。

现在让我们删除一条记录,只需在下拉列表中选择Delete,然后在url中指定带正斜杠的id,然后单击Send按钮。它会被自动删除。

最佳实践:

最佳实践是在构建api时以及在应用程序中使用api之前。通过Postman测试api会更好。

数据传输对象(DTO)

所以现在我们已经构建了这个API,但这个设计存在一些问题。我们的api接收或返回Customer对象。现在你可能会想到这种方法有什么问题?实际上,Customer对象是我们应用程序的域模型的一部分。当我们在应用程序中实现新功能时,它被认为是可以经常更改的实现细节,并且这些更改可能会抓取依赖于客户对象的现有客户端,即如果我们重命名或删除我们的属性,这会影响依赖于属性的客户端。所以基本上我们使api的协议尽可能稳定。在这里我们使用DTO。

DTO是普通数据结构,用于从服务器上的客户端传输数据,反之亦然,这就是我们称之为数据传输对象的原因。通过创建DTO,我们在重构域模型时减少了对API破坏的可能性。当然,我们应该记住,改变这些DTO可能会产生高昂成本。所以最重要的是我们的api不应该接收或返回Customer模型类对象。

在API中使用域对象的另一个问题是我们在应用程序中打开了安全漏洞。黑客可以轻松地在json中传递其他数据,并将它们映射到我们的域对象。如果不应该更新其中一个属性,黑客可以轻易绕过这个,但如果我们使用DTO,我们可以简单地排除可以更新的属性。因此,在项目中添加名为DTO的新文件夹并添加CustomerDTO类,并将Customer域模型类的所有属性及其数据注释属性复制并粘贴到CustomerDTO中。现在从CustomerDTO中删除导航属性,因为它正在创建与MembershipType域模型类的依赖关系。

namespace MyAPI.DTOs
{public class CustomerDTO{public int Id { get; set; }[Required][StringLength(255)]public string Name { get; set; }public bool IsSubscribedToNewsLetter { get; set; }public DateTime? Birthdate { get; set; }public byte MembershipTypeId { get; set; }}
}

接下来我们要在我们的api中使用CustomerDTO而不是Customer域类对象。因此,为了减少大量代码逐个绑定属性,我们使用Automapper。

Automapper

从Package Manager控制台安装automapper包。

PM > Install-Package Automapper -version:4.1

现在在App_Start(MappingProfile.cs)中添加新类并继承Profile。

using AutoMapper;namespace MyAPI.App_Start
{public class MappingProfile : Profile{}
}

现在创建构造函数并在两种类型之间添加映射配置。

public class MappingProfile : Profile
{public MappingProfile(){Mapper.CreateMap<Customer, CustomerDTO>();Mapper.CreateMap<CustomerDTO, Customer>();}
}

CreateMap的第一个参数是Source(源对象),第二个参数是destination(目标对象)。当我们使用CreateMap方法时,automapper会自动使用反射来扫描这些类型。它找到它们的属性并根据它们的名称对它们进行映射。这就是我们调用automapper(基于约定的映射工具)的原因,因为它使用属性名作为映射对象的约定。所以这里是映射配置文件,现在我们需要在应用程序启动时加载它。

现在打开Global.asax.cs文件并编写Application_Start()的代码

protected void Application_Start()
{Mapper.Initialize(c => c.AddProfile<MappingProfile>());GlobalConfiguration.Configure(WebApiConfig.Register);AreaRegistration.RegisterAllAreas();FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);
}

现在打开Api的CustomerController。让我们从这里开始改变。

// GET /api/customers
public IEnumerable<CustomerDTO> GetCustomers()
{return _context.Customers.ToList();
}

现在我们要返回CustomerDTO类型而不是Customer对象。现在我们需要将此Customer对象映射到CustomerDTO。所以我们使用linq扩展方法。

// GET /api/customers
public IEnumerable<CustomerDTO> GetCustomers()
{return _context.Customers.ToList().Select(Mapper.Map<Customer, CustomerDTO>);
}

Mapper.Map <Customer,CustomerDTO>

这个代表进行映射。我们可以看到我们没有放置函数调用小括号,因为我们没有在这里调用函数。我们在这里引用它。映射函数在执行时自动调用。

// GET /api/customers/1
public Customer GetCustomer(int id)
{var customer = _context.Customers.SingleOrDefault(x => x.Id == id);// This is part of the RESTful Conventionif (customer == null){throw new HttpResponseException(HttpStatusCode.NotFound);}return customer;
}

在这个函数中,因为我们返回一个对象所以我们不使用Select扩展方法。这里我们直接使用mapper

// GET /api/customers/1
public CustomerDTO GetCustomer(int id)
{var customer = _context.Customers.SingleOrDefault(x => x.Id == id);// This is part of the RESTful Conventionif (customer == null){throw new HttpResponseException(HttpStatusCode.NotFound);}return Mapper.Map<Customer, CustomerDTO>(customer);
}

现在进行下一个CreateCustomer操作,

// POST /api/customers
[HttpPost]
public CustomerDTO CreateCustomer(CustomerDTO customerDto)
{if (!ModelState.IsValid){throw new HttpResponseException(HttpStatusCode.BadRequest);}var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);_context.Customers.Add(customer);_context.SaveChanges();// Here we make our CustomerDto completely fill, because after// adding customer to Customer table (id is assigned to it)// & Now we assigned this id to customerDtocustomerDto.Id = customer.Id;return customerDto;
}

这就是我们如何使用Dto和Automapper。

现在让我们更新UpdateCustomer动作api方法。

// PUT /api/customers/1
[HttpPut]
public void UpdateCustomer(int id, CustomerDTO customerDto)
{if (!ModelState.IsValid){throw new HttpResponseException(HttpStatusCode.BadRequest);}var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);// Might be user sends invalid id.if (custmr == null){throw new HttpResponseException(HttpStatusCode.NotFound);}Mapper.Map<CustomerDTO, Customer>(customerDto, custmr);//custmr.Birthdate = customerDto.Birthdate;//custmr.IsSubscribedToNewsLetter = customerDto.IsSubscribedToNewsLetter;//custmr.Name = customerDto.Name;//custmr.MembershipTypeId = customerDto.MembershipTypeId;_context.SaveChanges();
}

这就是我们使用Automapper映射对象的方式。现在,automapper有一些在某些情况下可能会发现有用的功能,即如果您的属性名称不匹配,您可以覆盖默认约定,或者您可以从映射中排除某些属性,或者您可能想要创建自定义映射类。如果您想了解更多信息,可以从Automapper文档中学习。

IHttpActionResult

好吧看看这个CreateCustomer操作方法

// POST /api/customers
[HttpPost]
public CustomerDTO CreateCustomer(CustomerDTO customerDto)
{if (!ModelState.IsValid){throw new HttpResponseException(HttpStatusCode.BadRequest);}var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);_context.Customers.Add(customer);_context.SaveChanges();// Here we make our CustomerDto completely fill, because after// adding customerDto to Customer table (id is assigned to it)// & Now we assigned this id to customerDtocustomerDto.Id = customer.Id;return customerDto;
}

在这里,我们只是返回CustomerDto,最终会产生这样的响应

但是在restful约定中当我们创建资源时,状态代码应为201created所以我们需要更多地控制操作的响应返回并实现这一点,而不是返回CustomerDto,我们返回IHttpActionResult这个接口类似于我们在MVC框架中的ActionResult所以它由几个不同的类实现,这里在ApiController中,我们有很多方法来创建一个实现IHttpActionResult接口的类的实例。

现在,如果模型无效而不是抛出异常,请使用辅助方法BadRequest()

// POST /api/customers
[HttpPost]
public IHttpActionResult CreateCustomer(CustomerDTO customerDto)
{if (!ModelState.IsValid){return BadRequest();}var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);_context.Customers.Add(customer);_context.SaveChanges();// Here we make our CustomerDto completely fill, because after// adding customerDto to Customer table (id is assigned to it)// & Now we assigned this id to customerDtocustomerDto.Id = customer.Id;return Created(new Uri(Request.RequestUri + "/" + customer.Id),customerDto);
}

我们可以看到如果ModelState是无效的,它返回BadRequest,如果已经添加了customer,那么我们在Created()中使用我们最终创建新对象的对象返回具有此资源ID的Uri 。

看这里我们创建了另一个资源,现在状态为201 Created如果我们查看位置选项卡

这就是新创造的客户的uri。这是restful约定的一部分。所以在Web Api中,我们更倾向于使用IHttpActionResult作为操作的返回类型。

现在让我们对此Web Api中的其余操作进行更改。这是我们的Api的完整代码

public class CustomersController : ApiController
{private readonly ApplicationDbContext _context;public CustomersController(){_context = new ApplicationDbContext();}// GET /api/customerspublic IHttpActionResult GetCustomers(){return Ok(_context.Customers.ToList().Select(Mapper.Map<Customer, CustomerDTO>));}// GET /api/customers/1public IHttpActionResult GetCustomer(int id){var customer = _context.Customers.SingleOrDefault(x => x.Id == id);// This is part of the RESTful Conventionif (customer == null){return NotFound();}return Ok(Mapper.Map<Customer, CustomerDTO>(customer));}// POST /api/customers[HttpPost]public IHttpActionResult CreateCustomer(CustomerDTO customerDto){if (!ModelState.IsValid){return BadRequest();}var customer = Mapper.Map<CustomerDTO, Customer>(customerDto);_context.Customers.Add(customer);_context.SaveChanges();// Here we make our CustomerDto completely fill, because after// adding customerDto to Customer table (id is assigned to it)// & Now we assigned this id to customerDtocustomerDto.Id = customer.Id;return Created(new Uri(Request.RequestUri + "/" + customer.Id),customerDto);}   // PUT /api/customers/1[HttpPut]public IHttpActionResult UpdateCustomer(int id, CustomerDTO customerDto){if (!ModelState.IsValid){return BadRequest();}var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);// Might be user sends invalid id.if (custmr == null){return NotFound();}Mapper.Map<customerdto, customer="">(customerDto, custmr);_context.SaveChanges();return Ok(custmr);}// Delete /api/customers/1[HttpDelete]public IHttpActionResult DeleteCustomer(int id){var custmr = _context.Customers.SingleOrDefault(x => x.Id == id);// Might be user sends invalid id.if (custmr == null){return NotFound();}_context.Customers.Remove(custmr);// Now the object is marked as removed in memory// Now it is done_context.SaveChanges();return Ok(custmr);}}</customerdto,>

我在这里提一下这一点,因为你可以看到我们在UpdateCustomer中有2个参数。如果参数是原始类型,就像我们是int id那样我们将把这个参数放在路由url或查询字符串中。如果我们想要像我们这样初始化我们的复杂类型我们有CustomerDTO,那么我们将始终从postman中的请求体初始化它。所以不要在这里困扰这件事。

现在让我们通过post更新和删除json对象。如果您专注于UpdateCustomer操作参数,这里我们有第一个参数是记录ID,第二个参数是Customer领域模型类对象。

看它在请求头中使用Id,因为我们的实体在这里完成了。

但是如果我们不在请求标头中提供id,我们将得到错误。

而exceptionMessage是“属性'Id'是对象的关键信息的一部分,无法修改。”实际上这个异常发生在这一行,

Mapper.Map<CustomerDTO, Customer>(customerDto, custmr);

因为customerDto不包含Id,但custmr(Customer模型类的对象变量)具有Id属性。在这里,我们需要告诉Automapper在映射从customerDto到custmr时忽略Id。所以,来看映射配置文件

public class MappingProfile : Profile
{public MappingProfile(){Mapper.CreateMap<Customer, CustomerDTO>();Mapper.CreateMap<CustomerDTO, Customer>().ForMember(c => c.Id, opt => opt.Ignore());}
}

看它现在正在工作,

使用Web API

经过适当的api测试后,现在是使用api的时候了。最重要的是我想在这里提一下。现在我们的api准备好了,你可以在任何客户端使用这个api。在这里,我们向您展示使用Visual Studio应用程序进行使用的示例。如果你用我们构建这个api,那么你可以在jquery ajax的帮助下在php,python,任何框架应用程序中使用它。现在我们将使用jquery来调用我们的api。看这个屏幕,这里我展示了一些客户。

现在我们想要的是单击删除按钮删除行。因此,如果您了解我们如何在屏幕上呈现记录项,显然使用foreach循环。所以在删除锚点标签上点击我们还要记录id以将此id传递给web api删除操作并在成功时删除该行。

@foreach (var customer in Model)
{<tr><td>@Html.ActionLink(customer.Name, "Edit", "Customers", new { id = customer.Id }, null)</td>@if (customer.Birthdate != null){<td>@customer.Birthdate</td>}else{<td>Not Available</td>}<td><button data-customer-id="@customer.Id" class="btn btn-link js-delete">Delete</button></td></tr>
}

这是html。现在我想通过ajax调用我的api。

@section scripts{<script>$(document).ready(function() {$('#customers .js-delete').on('click',function () {var button = $(this);if (confirm('Are you sure you want to delete this client?')) {$.ajax({url: '/api/customers/' + button.attr('data-customer-id'),method: 'DELETE',success: function() {button.parents('tr').remove();}})}});});</script>
}

这就是我们使用ajax和api的方式。现在你可能在想这里我只是将id传递给客户api并定位Delete操作,在 success事件中我直接删除了行。您可能会以不同的方式思考这种情况,因为每个开发人员都有自己的品味。

您可能会想到,首先我们使用Delete方法删除记录,然后从Web Api的GetCustomers()方法获取所有记录,然后通过jquery的每个循环渲染所有这些项。但这种情况需要花费太多时间和效率。当我点击删除锚标签并在检查浏览器中显示结果时,状态为200 ok。这意味着一切正常,我们的代码(删除操作)正如我们所期望的那样工作。因此,我们不需要再次验证数据库中有多少项并通过每个循环呈现它们。

只需简化您的情况,并像我一样删除记录。

结论

因此,结论是当您使用Web Api时,始终遵循Restful约定。Web Api比基于SOAP的Web服务更加的轻量级。他们是跨平台的。Restful Http动词有助于在应用程序中插入,删除,更新,获取记录。在这里,我们看到我们如何使用postman,并有2个不同的窗格,如请求标头和响应标头。大多数时候,开发人员对如何使用jquery ajax使用Web Api操作感到困惑。在这里我们也使用了这个动作。

原文地址:https://www.codeproject.com/Articles/1252477/Building-a-Restful-API-With-ASP-NET-Web-API

使用ASP.NET Web API构建Restful API相关推荐

  1. asp编程工具_使用ASP.NET Core构建RESTful API的技术指南

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

  2. 使用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 ...

  3. 使用ASP.NET Core 3.x 构建 RESTful API - 1. 开始

    以前写过ASP.NET Core 2.x的REST API文章,今年再更新一下到3.0版本. 预备知识:ASP.NET Core 和 C# 工具:Visual Studio 2019最新版(VSCod ...

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

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

  5. dubbo2.5-spring4-mybastis3.2-springmvc4-mongodb3.4-redis3(十)之Spring MVC中使用 Swagger2 构建Restful API...

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010046908/article/details/55047193 1.Swagger2是什么? ...

  6. Spring MVC中使用 Swagger2 构建Restful API

    0.Spring MVC配置文件中的配置 [java] view plain copy <!-- 设置使用注解的类所在的jar包,只加载controller类 --> <span s ...

  7. pycharm构建虚拟环境_10分钟,带你用Python构建RESTful API 服务

    1. 前言 上一篇文章,介绍了使用 Java + Spring Boot + MyBatis 构建 RESTful API 的详细步骤:很多小伙伴表示,更愿意用 Python 编写 RESTful A ...

  8. 如何区别API、REST API、RESTful API和Web Service之间的异同

    当你看到API接口你会想起什么?是接口.第三方调用.还是API文档?初看你可能会觉得这太熟悉了,这不是系统开发日常系列吗?但你仔细想一想,你会发现API的概念在你脑海里是如此的模糊.如何你通过搜索引擎 ...

  9. 用 Flask 来写个轻博客 (36) — 使用 Flask-RESTful 来构建 RESTful API 之五

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 PUT 请求 DELETE 请求 测试 对一条已经存在的 posts ...

最新文章

  1. POPUP_TO_CONFIRM_LOSS_OF_DATA
  2. 查看hdfs目录的方法
  3. 《Jersey用户指南》翻译邀请
  4. 数据结构——二叉树的层次遍历
  5. React开发(259):react项目理解 ant design debug
  6. git+repo 代码提交
  7. python实现屏幕录制_GitHub - Sijiu/record-camera-and-screen: 录制摄像头和录制屏幕,两者之间可以轻易切换...
  8. ORA-04043: 对象 dba_data_files 不存在 BUG
  9. Unity3D占用内存太大的解决方法【先转,慢慢看】
  10. 作为字节跳动的研发面试官,有些话我不得不说!
  11. 【九天教您南方cass 9.1】 06 绘制方格网
  12. pythonmt4通讯swot矩阵_swot分析矩阵范例(各部门)
  13. cacti监控linux和windows磁盘io,为CactiEZ(或者Cacti)增加监控磁盘IO功能
  14. 手动实现获取微信openid
  15. Android开发:为什么你的学习效率如此低,为什么你很迷茫?
  16. 计算机天空之城音乐谱,天谕手游天空之城乐谱代码是什么
  17. excel学习-选择性粘贴(转置+跳过空白单元格+运算)
  18. 大一计算机专业学期计划范文,【大一学习计划22篇】_大一学习计划范文大全_2021年大一学习计划_东城教研...
  19. 黑马程序员——java语言基础部分——网络编程
  20. C#Winform中窗体的美化

热门文章

  1. mysql的count函数类型是什么意思_详细解读MySQL中COUNT函数的用法
  2. c语言计算分段函数_Rust能够取代C语言吗?
  3. 设计灵感|简单的文字和图片排版如何出彩?
  4. 喜庆红色C4D立体电商首焦模板|PSD分层格式,设计师大呼真香!
  5. 英雄联盟壁纸,你可以喜欢?
  6. 草莓甜品海报设计,甜出画面,受得住诱惑么?
  7. UI设计素材干货|可临摹的时尚播放页面模板
  8. java 异常返回json_Spring MVC全局异常后返回JSON异常数据
  9. c++ 14新的语法特性之返回类型推导
  10. libvirt Installation