记开发个人图书收藏清单小程序开发(五)Web开发
决定先开发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开发的更多相关文章
- 记开发个人图书收藏清单小程序开发(十)DB开发——新增图书信息
昨晚完成了Web端新增图书信息的功能,现在就差DB的具体实现了. 因为我把Book相关的信息拆分的比较多,所以更新有点小麻烦. 首先,我需要创建一个Book Type的Matter: 然后,将图片路径 ...
- 记开发个人图书收藏清单小程序开发(三)DB设计
主要是参考豆瓣的图书查询接口: https://api.douban.com/v2/book/isbn/:9780132350884 返回内容如下: { "rating": { & ...
- 记开发个人图书收藏清单小程序开发(九)Web开发——新增图书信息
书房信息初始化已完成,现在开始处理图书信息新增功能. 主要是实现之前New Razor Pages的后台部分. 新增需要保存的Model:Book.InitSpec.cs /Models/Book.I ...
- 记开发个人图书收藏清单小程序开发(六)Web开发
Web页面开发暂时是没有问题了,现在开始接上Ptager.BL的DB部分. 首先需要初始化用户和书房信息.因为还没有给其他多余的设计,所以暂时只有个人昵称和书房名称. 添加 Init Razor Pa ...
- 记开发个人图书收藏清单小程序开发(四)DB设计
早上起来,又改动了一下: 主要是,将非常用信息全部拆分出来,让Table尽量的小,小到不能继续拆分了,这样区分DB逻辑.增加了FileBank存储Book的封面图片,统一管理图片资源. 新添加的Typ ...
- 记开发个人图书收藏清单小程序开发(七)DB设计
前面的书房初始化的前端信息已经完善,所以现在开始实现DB的Script部分. 新增Action:Shelf_Init.sql svc.sql CREATE SCHEMA [svc] AUTHORIZA ...
- 微信小程序开发系列一:微信小程序的申请和开发环境的搭建
我最近也刚刚开始微信小程序的开发,想把我自学的一些心得写出来分享给大家. 这是第一篇,从零开始学习微信小程序开发.主要是小程序的注册和开发环境的搭建. 首先我们要在下列网址申请一个属于自己的微信小程序 ...
- 微信小程序开发系列七:微信小程序的页面跳转
微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 微信小程序开发系列三:微信小程序的调试方法 微信小程序开发系列四:微信小程序 ...
- 微信小程序开发系列二:微信小程序的视图设计
大家如果跟着我第一篇文章 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 一起动手,那么微信小程序的开发环境一定搭好了.效果就是能把该小程序的体验版以二维码的方式发送给其他朋友使用. 这个系列 ...
随机推荐
- red ant
Red Ant(红蚁)网络运维管理系统是IT运维管理系统,提供智能的B/S接口可视化人机界面,通过简单的操作实现全方位的网络专线.服务器.中间件.各种应 用程序.机房动力环境等监控管理,“化繁为简”, ...
- Windows环境下为PHP5.6安装redis扩展和memcached扩展
一.php安装redis扩展 1.使用phpinfo()函数查看PHP的版本信息,这会决定扩展文件版本 2.根据PHP版本号,编译器版本号和CPU架构, 选择php_redis-2.2 ...
- Cascade属性的取值
Cascade属性的取值有:1.none:忽略其他关联的对象,默认值.2.save-update:当session通过save(),update(),saveOrUpdate()方法来保存或更新对象时 ...
- MySQL GTID (四)
七. GTID的限制以及解决方案 7.1 事务中混合多个存储引擎,会产生多个GTID. 当使用GTID,在同一个事务中,更新包括了非事务引擎(MyISAM)和事务引擎(InnoDB)表的操作,就会导致 ...
- Android 包信息工具类
/** AndroidInfoUtils:安卓游戏包信息工具类**/ 1 public class AndroidInfoUtils { @SuppressWarnings("uncheck ...
- 自定义annotation-----转载
Java从JDK5.0开始便提供了四个meta-annotation用于自定义注解的时候使用,这四个注解为:@Target,@Retention,@Documented 和@Inherited. @T ...
- Redis 发布/定阅
[Redis 发布/定阅] 1.SUBSCRIBE channel [channel ...] 订阅给定的一个或多个频道的信息. 2.PSUBSCRIBE pattern [pattern ...] ...
- 若p是与10互质的质数,则p-1个9能被p整除
[若p是与10互质的质数,则k(p-1)个9能被p整除] 因为(p,10)=1,所以(p,10^k)=1.根据费马定理,10^(k*(p-1))-1|p. 而10^k*(p-1)-1是一个位数为(p- ...
- 使用Git将码云上的代码Clone至本地
1. 安装Git https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git Git的网站上有详细的分各种系统的安 ...
- canvas动画--demo
canvas动画:bubble