asp.net core web api 入门

本教程仅作为asp.net core web api 入门教程
参考网址:web api

前言

  • 这篇教程包含下面几个api:
    在这里插入图片描述

  • 应用的结构
    在这里插入图片描述

  • 项目结构预览:
    在这里插入图片描述

正文

下面开始演示操作流程及代码

1.创建项目

(1)文件->新建->项目
(2)web->ASP.NET Core Web应用程序
(3)API

如图:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 代码实现

2.1 增加一个Model类

先增加一个Models文件夹,然后右键增加一个TodoItem类

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}
2.2 创建 database context

这个类继承自 Microsoft.EntityFrameworkCore.DbContext
在Models文件夹下右键新建类TodoContext

using Microsoft.EntityFrameworkCore;namespace TodoApi.Models
{
    public class TodoContext : DbContext
    {
        public TodoContext(DbContextOptions<TodoContext> options)
            : base(options)
        {
        } 
        public DbSet<TodoItem> TodoItems { get; set; }
    }
}
2.3 注册 database context

在Startup类中进行注册

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;namespace TodoApi
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt => 
                opt.UseInMemoryDatabase("TodoList"));
            services.AddMvc()
                    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        } 
        
        public void Configure(IApplicationBuilder app)
        {
            app.UseMvc();
        }
    }
}

注意:

这里用的并不是数据库的数据,而是采用内存模仿的数据库来简单实现
services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));

如果要使用数据库,可以这样

var connection = @"Server=(localdb)\mssqllocaldb;Database=EFGetStarted.AspNetCore.NewDb;Trusted_Connection=True;ConnectRetryCount=0";
services.AddDbContext<TodoContext>
    (options => options.UseSqlServer(connection));

这里使用内存模仿的数据简单实现

2.4 增加一个controller

在controller文件夹下,右键添加controller,命名为TodoController

下面定义的controller类,还没有方法
使用了[ApiController]属性进行修饰,表示这个controller会对api请求进行响应
使用DI在controller中注入了context(ToDoContext)
如果数据库是空,会增加一个名字为iItem1的实体

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TodoApi.Models;

namespace TodoApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TodoController : ControllerBase
    {
        private readonly TodoContext _context;

        public TodoController(TodoContext context)
        {
            _context = context;

            if (_context.TodoItems.Count() == 0)
            {
                // Create a new TodoItem if collection is empty,
                // which means you can't delete all TodoItems.
                _context.TodoItems.Add(new TodoItem { Name = "Item1" });
                _context.SaveChanges();
            }
        }
    }
}
2.5 在controller 中 增加方法
// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
    return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

上面方法提供了两个接口

 - GET /api/todo
 - GET /api/todo/{id}

访问方式,如下:

 - https://localhost:<port>/api/todo
 - https://localhost:<port>/api/todo/1

路由和url路径

  • 这里会以api/[controller]作为路由

例如,上面两个接口的访问都是以api/todo作为前缀的

  • 如果[HttpGet]的属性有路由模板(例如:[HttpGet("/products")]),则直接加到路径后面。这里没有用路由模板。

可以在Action方法用注解的方式定义路由,例如上面两个接口

2.5.1 增加一个新建方法
// POST: api/Todo
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
    _context.TodoItems.Add(todoItem);
    await _context.SaveChangesAsync();

    return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
}

路由访问如下图:
在这里插入图片描述

2.5.2 增加一个PutTodoItem方法
// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
    if (id != todoItem.Id)
    {
        return BadRequest();
    }

    _context.Entry(todoItem).State = EntityState.Modified;
    await _context.SaveChangesAsync();

    return NoContent();
}

PutTodoItem类似于PostTodoItem,区别在与它用的Http Put方式。返回的是204(No Content)。

路由如下图:
在这里插入图片描述

2.5.3 增加一个DeleteTodoItem方法
// DELETE: api/Todo/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);
    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return todoItem;
}

返回的204(No Content)
用postman调用删除:
把方法设置成DELETE.
设置路径,例如:https://localhost:5001/api/todo/1

2.6 用Jquery调用api
配置静态文件和允许默认文件映射

如下图:
在这里插入图片描述

在wwwroot下增加一个index.html和site.js

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>To-do CRUD</title>
    <style>
        input[type='submit'], button, [aria-label] {
            cursor: pointer;
        }

        #spoiler {
            display: none;
        }

        table {
            font-family: Arial, sans-serif;
            border: 1px solid;
            border-collapse: collapse;
        }

        th {
            background-color: #0066CC;
            color: white;
        }

        td {
            border: 1px solid;
            padding: 5px;
        }
    </style>
</head>
<body>
    <h1>To-do CRUD</h1>
    <h3>Add</h3>
    <form action="javascript:void(0);" method="POST" onsubmit="addItem()">
        <input type="text" id="add-name" placeholder="New to-do">
        <input type="submit" value="Add">
    </form>

    <div id="spoiler">
        <h3>Edit</h3>
        <form class="my-form">
            <input type="hidden" id="edit-id">
            <input type="checkbox" id="edit-isComplete">
            <input type="text" id="edit-name">
            <input type="submit" value="Save">
            <a onclick="closeInput()" aria-label="Close">&#10006;</a>
        </form>
    </div>

    <p id="counter"></p>

    <table>
        <tr>
            <th>Is Complete</th>
            <th>Name</th>
            <th></th>
            <th></th>
        </tr>
        <tbody id="todos"></tbody>
    </table>

    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
    <script src="site.js"></script>
</body>
</html>

site.js

const uri = "api/todo";
let todos = null;
function getCount(data) {
  const el = $("#counter");
  let name = "to-do";
  if (data) {
    if (data > 1) {
      name = "to-dos";
    }
    el.text(data + " " + name);
  } else {
    el.text("No " + name);
  }
}

$(document).ready(function() {
  getData();
});

function getData() {
  $.ajax({
    type: "GET",
    url: uri,
    cache: false,
    success: function(data) {
      const tBody = $("#todos");

      $(tBody).empty();

      getCount(data.length);

      $.each(data, function(key, item) {
        const tr = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").on("click", function() {
                deleteItem(item.id);
              })
            )
          );

        tr.appendTo(tBody);
      });

      todos = data;
    }
  });
}

function addItem() {
  const item = {
    name: $("#add-name").val(),
    isComplete: false
  };

  $.ajax({
    type: "POST",
    accepts: "application/json",
    url: uri,
    contentType: "application/json",
    data: JSON.stringify(item),
    error: function(jqXHR, textStatus, errorThrown) {
      alert("Something went wrong!");
    },
    success: function(result) {
      getData();
      $("#add-name").val("");
    }
  });
}

function deleteItem(id) {
  $.ajax({
    url: uri + "/" + id,
    type: "DELETE",
    success: function(result) {
      getData();
    }
  });
}

function editItem(id) {
  $.each(todos, function(key, item) {
    if (item.id === id) {
      $("#edit-name").val(item.name);
      $("#edit-id").val(item.id);
      $("#edit-isComplete")[0].checked = item.isComplete;
    }
  });
  $("#spoiler").css({ display: "block" });
}

$(".my-form").on("submit", function() {
  const item = {
    name: $("#edit-name").val(),
    isComplete: $("#edit-isComplete").is(":checked"),
    id: $("#edit-id").val()
  };

  $.ajax({
    url: uri + "/" + $("#edit-id").val(),
    type: "PUT",
    accepts: "application/json",
    contentType: "application/json",
    data: JSON.stringify(item),
    success: function(result) {
      getData();
    }
  });

  closeInput();
  return false;
});

function closeInput() {
  $("#spoiler").css({ display: "none" });
}
2.7 改变这个项目的launch setting(运行时的配置)

打开launchSetting.json文件
删除launchUrl属性,强制应用index.html(项目的默认文件)
这样运行后,默认展示页面为index.html页面

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Vincent_yuan1991/article/details/85249052