决定先开发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样式完全不一样。

下面给出示例代码:

  1. <nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top">
  2. <div class="container">
  3. <a asp-page="/Index" class="navbar-brand">PTager Shelves</a>
  4. <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
  5. <span class="navbar-toggler-icon"></span>
  6. </button>
  7.  
  8. <div class="collapse navbar-collapse" id="navbarSupportedContent">
  9. <ul class="navbar-nav mr-auto">
  10. <li class="nav-item active">
  11. <a class="nav-link" asp-page="/Index">Home</a>
  12. </li>
  13. <li class="nav-item">
  14. <a class="nav-link" asp-page="/About">About</a>
  15. </li>
  16. <li class="nav-item">
  17. <a class="nav-link" asp-page="/Contact">Contact</a>
  18. </li>
  19. </ul>
  20. <partial name="_LoginPartial" />
  21. </div>
  22. </div>
  23. </nav>

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

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

  1. {
  2. "ConnectionStrings": {
  3. "DefaultConnection": "Server=.\\SQL2017;Database=PTager;Trusted_Connection=True;MultipleActiveResultSets=true"
  4. },
  5. "Logging": {
  6. "LogLevel": {
  7. "Default": "Warning"
  8. }
  9. },
  10. "AllowedHosts": "*"
  11. }

开始新增New Book功能。

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

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

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

  1. public class DoubanBookModel
  2. {
  3. public string title { get; set; }
  4. public string subtitle { get; set; }
  5. public IEnumerable<string> author { get; set; }
  6. public IEnumerable<string> translator { get; set; }
  7. public string isbn13 { get; set; }
  8. public string isbn10 { get; set; }
  9. public string author_intro { get; set; }
  10. public string summary { get; set; }
  11. public string publisher { get; set; }
  12. public string binding { get; set; }
  13. public string origin_title { get; set; }
  14. public int pages { get; set; }
  15. public string image { get; set; }
  16. public string pubdate { get; set; }
  17. public string catalog { get; set; }
  18. public IEnumerable<TagItem> tags { get; set; }
  19. public RatingItem rating { get; set; }
  20.  
  21. public sealed class TagItem
  22. {
  23. public int count { get; set; }
  24. public string name { get; set; }
  25. public string title { get; set; }
  26. }
  27. public sealed class SeriesItem
  28. {
  29. public int id { get; set; }
  30. public string title { get; set; }
  31. }
  32. public sealed class RatingItem
  33. {
  34. public int max { get; set; }
  35. public int min { get; set; }
  36. public int numRaters { get; set; }
  37. public string average { get; set; }
  38. }
  39. }

/Pages/Sheves/New.cshtml:

  1. @page
  2. @model NewModel
  3. @{
  4. ViewData["Title"] = "New Book";
  5. }
  6. <nav aria-label="breadcrumb">
  7. <ol class="breadcrumb">
  8. <li class="breadcrumb-item"><a asp-page="/Index">Home</a></li>
  9. <li class="breadcrumb-item"><a asp-page="/My Books/Index">My Books</a></li>
  10. <li class="breadcrumb-item active" aria-current="page">New Book</li>
  11. </ol>
  12. </nav>
  13. <form method="get">
  14. <div class="input-group input-group-lg mb-3">
  15. <div class="input-group-prepend">
  16. <span class="input-group-text" id="basic-addon1">ISBN #</span>
  17. </div>
  18. <input name="isbn" class="form-control" autofocus autocomplete="off" placeholder="ISBN #">
  19. <div class="input-group-append">
  20. <button class="btn btn-secondary btn-lg" type="submit">Search</button>
  21. </div>
  22. </div>
  23. </form>
  24. <hr />
  25. @if (Model.DoubanBook != null)
  26. {
  27. var item = Model.DoubanBook;
  28. <div class="media">
  29. @*<img class="align-self-start mr-3" src="@item.image" alt="Generic placeholder image">*@
  30. <div class="media-body">
  31. <h3 class="mt-0">@item.title<small class="ml-3">@item.subtitle</small></h3>
  32. <p><strong>Origin Title: </strong> @item.origin_title</p>
  33. <p><strong>Author: </strong> @string.Join("、", item.author)</p>
  34. <p><strong>Translator: </strong> @string.Join("、", item.translator)</p>
  35. <p>
  36. <strong>Pubdate: </strong> @item.pubdate
  37. <strong class="ml-3">Publisher: </strong> @item.publisher
  38. <strong class="ml-3">Binding: </strong> @item.binding
  39. <strong class="ml-3">Pages: </strong> @item.pages
  40. </p>
  41. <p>
  42. <strong>ISBN: </strong> @item.isbn13
  43. </p>
  44. <p><strong class="mr-3">Author Intro:</strong> @item.author_intro</p>
  45. <p><strong class="mr-3">Summary:</strong>@item.summary</p>
  46. @foreach (var tag in item.tags)
  47. {
  48. <span class="badge badge-info">@tag.name</span>
  49. }
  50. </div>
  51. </div>
  52. <hr />
  53. <form method="post">
  54. <input type="hidden" asp-page="IsbnNbr">
  55. <button class="btn btn-warning" type="submit">Add To My Books</button>
  56. </form>
  57. }

/Pages/Sheves/New.cshtml.cs:

  1. public class NewModel : PageModel
  2. {
  3. [BindProperty]
  4. public string IsbnNbr { get; set; }
  5. public DoubanBookModel DoubanBook { get; set; }
  6.  
  7. public async Task OnGetAsync(string isbn)
  8. {
  9. IsbnNbr = isbn?.Trim() ?? string.Empty;
  10. if (validIsbnNbr(IsbnNbr))
  11. {
  12. DoubanBook = await getDoubanBook();
  13. }
  14. }
  15. private async Task<DoubanBookModel> getDoubanBook()
  16. {
  17. var url = $"https://api.douban.com/v2/book/isbn/:{IsbnNbr}";
  18. var result = await HttpGetAsync(url);
  19. return JsonConvert.DeserializeObject<DoubanBookModel>(result);
  20. }
  21. public async Task<string> HttpGetAsync(string url, Encoding encoding = null)
  22. {
  23. using (var httpClient = new HttpClient())
  24. {
  25. return await httpClient.GetStringAsync(url);
  26. }
  27. }
  28.  
  29. private bool validIsbnNbr(string isbn)
  30. => !string.IsNullOrEmpty(IsbnNbr) && (IsbnNbr.Length == || IsbnNbr.Length == );
  31. }

好了,现在可以直接从豆瓣图书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. linux记录每个用户执行的命令

    1.在/etc/profile中添加如下代码: #history USER_IP=`>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'` HISTD ...

  2. C#遍历XmlDocument对象所有节点名称、类型、属性(Attribute)

    C#遍历XmlDocument对象所有节点名称.类型.属性(Attribute) 源码下载 代码 static void Main(string[] args) { System.Xml.XmlDoc ...

  3. Android 多线程注意事项

    参考:http://blog.csdn.net/x86android/article/details/14161981 http://geeksun.iteye.com/blog/1447708 An ...

  4. bootstrap更新数据层

    mq推送数据,表格实时更新,发现销毁表格不太合适,整体表格闪动,于是选择更新数据层. 先初始化表格,然后在推送数据的时候先循环遍历数据 例如: initDevTable(data.operatingL ...

  5. jeesite快速开发平台(四)----数据库各表一览

    转自:https://blog.csdn.net/u011781521/article/details/55194309

  6. kubenetes GPU

    https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/#deploying-nvidia-gpu-device-plugin 1. ...

  7. 禁止ImageCapture自动启动

    [禁止ImageCapture自动启动] 打开ImageCapture,点开左下角菜单,把Connecting this iPhone opens:的内容改为以下选项即可.

  8. PHP 文件处理(综合)

    1.获取远程文件大小:php获得远程文件大小的函数php获得远程文件大小的函数文件的大小函数为:filesize()文件是否存在的函数为:file_exits();但是这两个函数只针对本地那么:远程文 ...

  9. Linux中如何克隆KVM虚拟机

    转载:https://yq.aliyun.com/articles/64860 作者 digoal 日期 2016-11-11 标签 Linux , KVM , 虚拟化 , 克隆 背景 当需要批量部署 ...

  10. [Selenium]等待元素出现之后再消失,界面上的loading icon都属于这种类型,之前的方法总是卡死,换这种方法目前还好用的

    等待元素出现之后再消失,界面上的loading icon都属于这种类型,之前的方法总是卡死,换这种方法目前还好用的 /** * Check if the element present with cu ...