决定先开发Web端试试。

新增Web应用:

选择ASP.NET Core Web Application,填写好Name和Location,然后点击OK。

注意红框标出来的,基于.NET Core 2.1版本。登录认证用了微软自带的Identity。Template选择Web Application,也即最新的Razor Pages试图引擎模式。

创建完毕,因为该Template自带的bootstrap还是3.3.7,所以从中文网站下载最新的bootstrap 4.x,同时还需要下载的是popper js插件(如果用到dropdown组件的话,不大明白为何新版Bootstrap不自带这个)。_Layout中的css和js引用也需要同步更新一下,还有就是Navbar菜单需要更新,因为3.x和4.x用的class样式完全不一样。

下面给出示例代码:

 <nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top">
<div class="container">
<a asp-page="/Index" class="navbar-brand">PTager Shelves</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-page="/About">About</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-page="/Contact">Contact</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
</div>
</nav>

到此,Web项目基本改造完成了。

当然,前面说到我还是用PTager的现有的登录DB做登录功能,很简单,直接修改appsettings.json文件中的DB连接字符串就好了(如果没有也没事,直接用本地的空DB,注册的时候会提示如何自己创建DB)。

 {
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQL2017;Database=PTager;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

开始新增New Book功能。

先check豆瓣图书的api能不能正常调用。

在Pages文件夹下New Folder:Shelves,继续在Shelves文件夹New Item=>Razor Pages,Name直接改为:New。

为了接受豆瓣图书API获取的参数信息,先定义一个DoubanBookModel:

     public class DoubanBookModel
{
public string title { get; set; }
public string subtitle { get; set; }
public IEnumerable<string> author { get; set; }
public IEnumerable<string> translator { get; set; }
public string isbn13 { get; set; }
public string isbn10 { get; set; }
public string author_intro { get; set; }
public string summary { get; set; }
public string publisher { get; set; }
public string binding { get; set; }
public string origin_title { get; set; }
public int pages { get; set; }
public string image { get; set; }
public string pubdate { get; set; }
public string catalog { get; set; }
public IEnumerable<TagItem> tags { get; set; }
public RatingItem rating { get; set; } public sealed class TagItem
{
public int count { get; set; }
public string name { get; set; }
public string title { get; set; }
}
public sealed class SeriesItem
{
public int id { get; set; }
public string title { get; set; }
}
public sealed class RatingItem
{
public int max { get; set; }
public int min { get; set; }
public int numRaters { get; set; }
public string average { get; set; }
}
}

/Pages/Sheves/New.cshtml:

 @page
@model NewModel
@{
ViewData["Title"] = "New Book";
}
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-page="/Index">Home</a></li>
<li class="breadcrumb-item"><a asp-page="/My Books/Index">My Books</a></li>
<li class="breadcrumb-item active" aria-current="page">New Book</li>
</ol>
</nav>
<form method="get">
<div class="input-group input-group-lg mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">ISBN #</span>
</div>
<input name="isbn" class="form-control" autofocus autocomplete="off" placeholder="ISBN #">
<div class="input-group-append">
<button class="btn btn-secondary btn-lg" type="submit">Search</button>
</div>
</div>
</form>
<hr />
@if (Model.DoubanBook != null)
{
var item = Model.DoubanBook;
<div class="media">
@*<img class="align-self-start mr-3" src="@item.image" alt="Generic placeholder image">*@
<div class="media-body">
<h3 class="mt-0">@item.title<small class="ml-3">@item.subtitle</small></h3>
<p><strong>Origin Title: </strong> @item.origin_title</p>
<p><strong>Author: </strong> @string.Join("、", item.author)</p>
<p><strong>Translator: </strong> @string.Join("、", item.translator)</p>
<p>
<strong>Pubdate: </strong> @item.pubdate
<strong class="ml-3">Publisher: </strong> @item.publisher
<strong class="ml-3">Binding: </strong> @item.binding
<strong class="ml-3">Pages: </strong> @item.pages
</p>
<p>
<strong>ISBN: </strong> @item.isbn13
</p>
<p><strong class="mr-3">Author Intro:</strong> @item.author_intro</p>
<p><strong class="mr-3">Summary:</strong>@item.summary</p>
@foreach (var tag in item.tags)
{
<span class="badge badge-info">@tag.name</span>
}
</div>
</div>
<hr />
<form method="post">
<input type="hidden" asp-page="IsbnNbr">
<button class="btn btn-warning" type="submit">Add To My Books</button>
</form>
}

/Pages/Sheves/New.cshtml.cs:

     public class NewModel : PageModel
{
[BindProperty]
public string IsbnNbr { get; set; }
public DoubanBookModel DoubanBook { get; set; } public async Task OnGetAsync(string isbn)
{
IsbnNbr = isbn?.Trim() ?? string.Empty;
if (validIsbnNbr(IsbnNbr))
{
DoubanBook = await getDoubanBook();
}
}
private async Task<DoubanBookModel> getDoubanBook()
{
var url = $"https://api.douban.com/v2/book/isbn/:{IsbnNbr}";
var result = await HttpGetAsync(url);
return JsonConvert.DeserializeObject<DoubanBookModel>(result);
}
public async Task<string> HttpGetAsync(string url, Encoding encoding = null)
{
using (var httpClient = new HttpClient())
{
return await httpClient.GetStringAsync(url);
}
} private bool validIsbnNbr(string isbn)
=> !string.IsNullOrEmpty(IsbnNbr) && (IsbnNbr.Length == || IsbnNbr.Length == );
}

好了,现在可以直接从豆瓣图书API获取到返回结果了,并且能展示在页面:

记开发个人图书收藏清单小程序开发(五)Web开发的更多相关文章

  1. 记开发个人图书收藏清单小程序开发(十)DB开发——新增图书信息

    昨晚完成了Web端新增图书信息的功能,现在就差DB的具体实现了. 因为我把Book相关的信息拆分的比较多,所以更新有点小麻烦. 首先,我需要创建一个Book Type的Matter: 然后,将图片路径 ...

  2. 记开发个人图书收藏清单小程序开发(三)DB设计

    主要是参考豆瓣的图书查询接口: https://api.douban.com/v2/book/isbn/:9780132350884 返回内容如下: { "rating": { & ...

  3. 记开发个人图书收藏清单小程序开发(九)Web开发——新增图书信息

    书房信息初始化已完成,现在开始处理图书信息新增功能. 主要是实现之前New Razor Pages的后台部分. 新增需要保存的Model:Book.InitSpec.cs /Models/Book.I ...

  4. 记开发个人图书收藏清单小程序开发(六)Web开发

    Web页面开发暂时是没有问题了,现在开始接上Ptager.BL的DB部分. 首先需要初始化用户和书房信息.因为还没有给其他多余的设计,所以暂时只有个人昵称和书房名称. 添加 Init Razor Pa ...

  5. 记开发个人图书收藏清单小程序开发(四)DB设计

    早上起来,又改动了一下: 主要是,将非常用信息全部拆分出来,让Table尽量的小,小到不能继续拆分了,这样区分DB逻辑.增加了FileBank存储Book的封面图片,统一管理图片资源. 新添加的Typ ...

  6. 记开发个人图书收藏清单小程序开发(七)DB设计

    前面的书房初始化的前端信息已经完善,所以现在开始实现DB的Script部分. 新增Action:Shelf_Init.sql svc.sql CREATE SCHEMA [svc] AUTHORIZA ...

  7. 微信小程序开发系列一:微信小程序的申请和开发环境的搭建

    我最近也刚刚开始微信小程序的开发,想把我自学的一些心得写出来分享给大家. 这是第一篇,从零开始学习微信小程序开发.主要是小程序的注册和开发环境的搭建. 首先我们要在下列网址申请一个属于自己的微信小程序 ...

  8. 微信小程序开发系列七:微信小程序的页面跳转

    微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 微信小程序开发系列三:微信小程序的调试方法 微信小程序开发系列四:微信小程序 ...

  9. 微信小程序开发系列二:微信小程序的视图设计

    大家如果跟着我第一篇文章 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 一起动手,那么微信小程序的开发环境一定搭好了.效果就是能把该小程序的体验版以二维码的方式发送给其他朋友使用. 这个系列 ...

随机推荐

  1. tensorflow-windows下安装,python3.6

    安装: pip install tensorflow ps:我第一次安装了,但是导入却失败了. 进入\python3\Lib\site-packages\删除了tensorflow,再次pip ins ...

  2. html5 filereader 读取图片信息

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. 基础 ByteBuffer 和 ByteBuf

    缓冲区 ByteBuffer buffer = ByteBuffer.allocate(); ByteBuf https://www.jianshu.com/p/3fbf54b8e8ec

  4. Eclipse去掉对jQuery的错误提示

    1.I have found that I can leave the JavaScript Validator enable and ignore specific files by adding ...

  5. 新手C#重载、重写的学习2018.08.04

    重载:在同一类(class)中,使用相同的方法名称,不同的参数和(不一定)不同的返回值类型构造成的方法. 举例: class OverLoadTest { public void Hello() { ...

  6. OGNL特殊符号的使用

    ---------------------siwuxie095 # 的使用 1.使用 # 获取 context 中的数据 「值栈分为 root 和 context 两部分」 2.如:向 Request ...

  7. 单词搜索 II · Word Search II

    [抄题]: 给出一个由小写字母组成的矩阵和一个字典.找出所有同时在字典和矩阵中出现的单词.一个单词可以从矩阵中的任意位置开始,可以向左/右/上/下四个相邻方向移动. 给出矩阵: doafagaidca ...

  8. Laravel/Homestead storage:link -> symlink(): Protocol error

    I'm trying to run the following artisan command: php artisan storage:link I get this error: [ErrorEx ...

  9. [Selenium]对于某些对话框即有可能弹出来,也有可能不弹出来,这种应该怎么处理呢?

    界面上如果有一个对话框可能弹出来,也可能不弹出,我们都要认为是正常,应该怎么处理呢? /** * check if release notes dialog present * @author j * ...

  10. 网络爬虫--requests库中两个重要的对象

    当我们使用resquests.get()时,返回的时response的对象,他包含服务器返回的所有信息,也包含请求的request的信息. 首先: response对象的属性有以下几个, r.stat ...