专栏首页NetCore【翻译】在Visual Studio中使用Asp.Net Core MVC创建你的第一个Web API应用(一)

【翻译】在Visual Studio中使用Asp.Net Core MVC创建你的第一个Web API应用(一)

HTTP is not just for serving up web pages. It’s also a powerful platform for building APIs that expose services and data. HTTP is simple, flexible, and ubiquitous. Almost any platform that you can think of has an HTTP library, so HTTP services can reach a broad range of clients, including browsers, mobile devices, and traditional desktop apps.


In this tutorial, you’ll build a simple web API for managing a list of "to-do" items. You won’t build any UI in this tutorial.

在本教程中,你将建造一个简单的web api去管理“to-do”项目,在整个过程中不需要构建UI。

ASP.NET Core has built-in support for MVC building Web APIs. Unifying the two frameworks makes it simpler to build apps that include both UI (HTML) and APIs, because now they share the same code base and pipeline.

Asp.Net Core已经内置了使用MVC创建Web APIs。统一了两个框架可以更轻松的创建应用,包括UI(Html)和APIs,因为现在它们共用了相同的基类和管道。


Here is the API that you’ll create:


The following diagram shows the basic design of the app.


  • The client is whatever consumes the web API (browser, mobile app, and so forth). We aren’t writing a client in this tutorial. We'll use Postman to test the app.
  • 在这里我们将用Postman来测试应用,其他任何支持web api(浏览器,移动应用等等)在这里不再讲述。
  • A model is an object that represents the data in your application. In this case, the only model is a to-do item. Models are represented as simple C# classes (POCOs).
  • 在这个应用中一个模型代表一个对象,在这个范例里,仅仅只有TO-DO item模型。这个模型就是简单的C#类
  • A controller is an object that handles HTTP requests and creates the HTTP response. This app will have a single controller.
  • 控制器就是控制HTTP请求和返回的对象,这个应用只有简单的控制器。
  • To keep the tutorial simple, the app doesn’t use a database. Instead, it just keeps to-do items in memory. But we’ll still include a (trivial) data access layer, to illustrate the separation between the web API and the data layer. For a tutorial that uses a database, see Building your first ASP.NET Core MVC app with Visual Studio.
  • 为了保持简单范例,这个应用不使用数据库,我们仅需要把对象保存在内存中。但是我们还是应该保持创建一个数据访问层,这样能更好的表示web API和数据层之间的分离。如果需要使用数据库,可以参考:Building your first ASP.NET Core MVC app with Visual Studio


Start Visual Studio. From the File menu, select New > Project.

打开Visual Studio,从File目录中,选择New > Project。

Select the ASP.NET Core Web Application (.NET Core) project template. Name the project TodoApi, clear Host in the cloud, and tap OK.

选择ASP.NET Core Web Application (.NET Core) 项目模板,名字为:TodoApi,不勾选Host in the cloud,点击OK。

In the New ASP.NET Core Web Application (.NET Core) - TodoApi dialog, select the Web API template. Tap OK.

New ASP.NET Core Web Application (.NET Core) - TodoApi对话框中,选择Web Api模板,点击OK。


Add a folder named "Models". In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder Models.

在解决方案目录中,添加一个名为“Models”文件夹,右键项目-选择Add > New Folder,取名:Models。

Add a TodoItem class. Right-click the Models folder and select Add > Class. Name the class TodoItem and tap Add.

添加TodoItem类,右键Models目录,选择Add > Class ,取名:TodoItem,点击添加。

Replace the generated code with:


namespace TodoApi.Models
    public class TodoItem
        public string Key { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }


A repository is an object that encapsulates the data layer. The repository contains logic for retrieving and mapping data to an entity model. Even though the example app doesn’t use a database, it’s useful to see how you can inject a repository into your controllers. Create the repository code in the Models folder.


Defining a repository interface named ITodoRepository. Use the class template (Add New Item > Class)

定义一个名为:ITodoRepository的repository接口,使用类模板(Add New Item > Class)

using System.Collections.Generic;

namespace TodoApi.Models
    public interface ITodoRepository
        void Add(TodoItem item);
        IEnumerable<TodoItem> GetAll();
        TodoItem Find(string key);
        TodoItem Remove(string key);
        void Update(TodoItem item);

This interface defines basic CRUD operations.


Add a TodoRepository class that implements ITodoRepository:


using System;
using System.Collections.Generic;
using System.Collections.Concurrent;

namespace TodoApi.Models
    public class TodoRepository : ITodoRepository
        private static ConcurrentDictionary<string, TodoItem> _todos =
              new ConcurrentDictionary<string, TodoItem>();

        public TodoRepository()
            Add(new TodoItem { Name = "Item1" });

        public IEnumerable<TodoItem> GetAll()
            return _todos.Values;

        public void Add(TodoItem item)
            item.Key = Guid.NewGuid().ToString();
            _todos[item.Key] = item;

        public TodoItem Find(string key)
            TodoItem item;
            _todos.TryGetValue(key, out item);
            return item;

        public TodoItem Remove(string key)
            TodoItem item;
            _todos.TryRemove(key, out item);
            return item;

        public void Update(TodoItem item)
            _todos[item.Key] = item;

Build the app to verify you don't have any compiler errors.



By defining a repository interface, we can decouple the repository class from the MVC controller that uses it. Instead of instantiating a TodoRepository inside the controller we will inject an ITodoRepository using the built-in support in ASP.NET Core for dependency injection.

因为定义了一个repository接口,我们能够使repository类和MVC控制器能够分离使用。我们不需要在controller中实例化一个TodoRepository类,只需要使用ASP.NET Core内置的依赖注入即可。

This approach makes it easier to unit test your controllers. Unit tests should inject a mock or stub version of ITodoRepository. That way, the test narrowly targets the controller logic and not the data access layer.


In order to inject the repository into the controller, we need to register it with the DI container. Open the Startup.cs file. Add the following using directive:


using TodoApi.Models;

In the ConfigureServices method, add the highlighted code:


public void ConfigureServices(IServiceCollection services)
    // Add framework services.

    services.AddSingleton<ITodoRepository, TodoRepository>();


In Solution Explorer, right-click the Controllers folder. Select Add > New Item. In the Add New Item dialog, select the Web API Controller Class template. Name the class TodoController.

在解决方案面板中,右键Controllers目录,选择Add > New Item。在添加对话框中,选择Web Api Controller Class模板,取名:TodoController。

Replace the generated code with the following:


using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using TodoApi.Models;

namespace TodoApi.Controllers
    public class TodoController : Controller
        public TodoController(ITodoRepository todoItems)
            TodoItems = todoItems;
        public ITodoRepository TodoItems { get; set; }

This defines an empty controller class. In the next sections, we'll add methods to implement the API.



To get to-do items, add the following methods to the TodoController class.


public IEnumerable<TodoItem> GetAll()
    return TodoItems.GetAll();

[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
    var item = TodoItems.Find(id);
    if (item == null)
        return NotFound();
    return new ObjectResult(item);

These methods implement the two GET methods:


  • GET /api/todo
  • GET /api/todo/{id}

Here is an example HTTP response for the GetAll method:


HTTP/1.1 200 OK
   Content-Type: application/json; charset=utf-8
   Server: Microsoft-IIS/10.0
   Date: Thu, 18 Jun 2015 20:51:10 GMT
   Content-Length: 82


Later in the tutorial I'll show how you can view the HTTP response using Postman.

在范例后面,我将演示如何使用Postman查看HTTP response。


The [HttpGet] attribute (HttpGetAttribute) specifies an HTTP GET method. The URL path for each method is constructed as follows:

HttpGet特性提供了一个HTTP Get方法。这个方法构造了如下的URL路径:

  • Take the template string in the controller’s route attribute, [Route("api/[controller]")]
  • 在控制器的路由特性中查看模板字符串,[Route("api/[controller]")]
  • Replace "[Controller]" with the name of the controller, which is the controller class name minus the "Controller" suffix. For this sample, the controller class name is TodoController and the root name is "todo". ASP.NET Core routing is not case sensitive.
  • 替换Controller名,类必须以Controller结尾。这个范例里我们使用TodoController作为类名,Asp.Net Core路由是不区分大小写的。
  • If the [HttpGet] attribute has a template string, append that to the path. This sample doesn't use a template string.
  • 如果这个HttpGet特性含有模板字符的话,添加相应路径,我们不使用默认字符。

In the GetById method:


[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)

"{id}" is a placeholder variable for the ID of the todo item. When GetById is invoked, it assigns the value of "{id}" in the URL to the method's id parameter.


Name = "GetTodo" creates a named route and allows you to link to this route in an HTTP Response. I'll explain it with an example later. See Routing to Controller Actions for detailed information.

[Name="GetTodo" ]创建了一个名为GetTodo的路由名,它允许在HTTP响应中链接到你的路由上。稍后会做演示,详见:Routing to Controller Actions


The GetAll method returns an IEnumerable. MVC automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this method is 200, assuming there are no unhandled exceptions. (Unhandled exceptions are translated into 5xx errors.)


In contrast, the GetById method returns the more general IActionResult type, which represents a wide range of return types. GetById has two different return types:


  • If no item matches the requested ID, the method returns a 404 error. This is done by returning NotFound.
  • 如果没有匹配到响应的item,这个方法返回404错误,返回NotFound。
  • Otherwise, the method returns 200 with a JSON response body. This is done by returning an ObjectResult
  • 相反,这个方法返回200代码并响应一个JSON对象,类型为:ObjectResult。





0 条评论
登录 后参与评论


  • 【翻译】在Visual Studio中使用Asp.Net Core MVC创建第一个Web Api应用(二)

    运行应用 In Visual Studio, press CTRL+F5 to launch the app. Visual Studio launches a...

  • 【翻译】使用Visual Studio创建Asp.Net Core MVC (一)

    This tutorial will teach you the basics of building an ASP.NET Core MVC web app ...

  • 【翻译】在Mac上使用VSCode创建你的第一个Asp.Net Core应用

    Setting Up Your Development Environment 设置你的开发环境 To setup your development machi...

  • Flink是如何kafka读取数据的

    版权声明:本文为博主原创,欢迎转载,转载请标明出处 Blog Address:http://blog.csdn.net/jsjsjs1789 https...

  • Runtime Errors - START_CALL_SICK

    |Short Text ...

    Jerry Wang
  • 栈:我们能干的事情多着呢

    老师:同学们大家好,这些节课我们来讲一下栈。那么什么是栈呢。栈是一种后进先出的线性表,它是按照后进先出的原则存储数据。Last In First Out ,简称...

  • Intro to Python Image Processing in Computational Photography

    Computational photography is about enhancing the photographic process with compu...

  • SAP WebClient UI页面标签的决定逻辑介绍

    In this blog we have discussed the logic how the correct UI view configuration i...

    Jerry Wang
  • hdu----(5053)the Sum of Cube(签到题,水体)

    the Sum of Cube Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32...

  • Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3)(A.B.C,3道暴力题,C可二分求解)

    A. Is it rated? time limit per test:2 seconds memory limit per test:256 megabyte...