響應式上午 ( bs + js or jq ( 利用bs已經寫好的函式庫完成
#Bootstrap components 元/組件
##標籤/元素 data 屬性
##alert 警報 警告 bs class
###keyword
alert-danger
alert-dark
alert-info
alert-success
&開頭;結尾 ( × 特殊符號 X
#bs js庫 ( 第一次講 ( alert關閉功能
data 開頭的屬性 ( 事件發生做甚麼
data-dismiss=”alert” ( 被消失
沒反應? ( 要link jq庫近來 後再進 bs庫 ( js 寫 jq庫 , jq庫 寫 bs庫
再來完成某個小功能
下id在 alert class div上
用jq選擇器 當選擇器被關掉時 執行某funtion
Log ? api 存到資料庫
###/RWD/20Alert.html
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="MyStyle.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<div class="alert alert-danger">
您現在是最高權限,用完後請馬上登出!!
</div>
<div class="alert alert-warning">
您現在是最高權限,用完後請馬上登出!!
</div>
<div class="alert alert-info">
您現在是最高權限,用完後請馬上登出!!
</div>
<div class="alert alert-dark">
您現在是最高權限,用完後請馬上登出!!
</div>
<hr />
<div class="alert alert-danger">
您現在是最高權限,用完後請馬上登出!!<a href="#" class="alert-link">點我登出系統</a>
</div>
<div class="alert alert-info">
您現在是最高權限,用完後請馬上登出!!<a href="#" class="alert-link">點我登出系統</a>
</div>
<hr />
<div class="alert alert-success">
<h4>您好!!系統管理員!!</h4>
<p>您現在是最高權限,用完後請馬上登出!!</p>
<hr />
<p>目前登入系統是危險的!!請注意密碼外洩或其他資安問題</p>
</div>
<div class="alert alert-dark">
您現在是最高權限,用完後請馬上登出!!
<button type="button" class="close" data-dismiss="alert">
×
</button>
</div>
<div class="alert alert-danger" id="myAlert">
<button type="button" class="close" data-dismiss="alert">
×
</button>
<h4>您好!!系統管理員!!</h4>
<p>您現在是最高權限,用完後請馬上登出!!</p>
<hr />
<p>目前登入系統是危險的!!請注意密碼外洩或其他資安問題</p>
</div>
</div>
<script src="Scripts/jquery-3.0.0.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script>
$('#myAlert').on('closed.bs.alert', function () {
alert("您關閉了系統警告訊息!!記得用完後馬上登出系統!!");
});
</script>
</body>
</html>
以上其實就是jq show 跟 hide 還能跑特效 fade in fade out
只是說用它的可以很快,而且它沒寫的就沒得用還是要自己寫
##題外話 如果用 jq開發 一個空白網站應該至少要有
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="MyStyle.css" rel="stylesheet" />
</head>
<body>
<div class="container">
</div>
<script src="Scripts/jquery-3.0.0.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
</body>
</html>
##badge ( 小按鈕 小提示
###keyword
Badge
Badge-danger
.
.
.
Ex 站內信 ( 已讀未讀
sr seo 排名 ??? class sr-only 會被盲用電腦讀出
### /RWD/21Badge.html
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="MyStyle.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<h1>This is a h1 heading!!<span class="badge badge-danger">New</span></h1>
<button class="btn btn-primary">
未讀郵件<span class="badge badge-light">5</span>
</button>
<button class="btn btn-success">
未讀郵件<span class="badge badge-light">5</span>
</button>
<button class="btn btn-danger">
未讀郵件<span class="badge badge-light">5</span>
<span class="sr-only">未讀郵件5封</span>
</button>
<hr>
<span class="badge badge-primary">primary</span>
<span class="badge badge-success">success</span>
<span class="badge badge-info">info</span>
<hr>
<span class="badge badge-primary badge-pill">primary</span>
<span class="badge badge-pill badge-success">success</span>
<span class="badge badge-info badge-pill">info</span>
<hr>
<a href="#" class="badge badge-primary">primary</a>
<a href="#" class="badge badge-success">success</a>
<a href="#" class="badge badge-info">info</a>
</div>
<script src="Scripts/jquery-3.0.0.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
</body>
</html>
##BreadCrumb 麵包屑
網站設計是一層一層的Sitemap邏輯性的
但是實體的網站其實是網狀的藉由Url可以直接跳轉
而網站地圖就是麵包屑
網站地圖一定跟選單有關
架構 ( 階層 SiteMap => Menu選單
###keyword
breadcrumb
breadcrumb-item
breadcrumb 搭配 超連結
active作用中(自己去寫? (每個 combind的效果都不一樣 要去參考庫上的屬性
4版本的跟3版本的改的地方不一樣但其實就是原生的css或js寫的庫
不改的屬性不用貼進來 不用重複寫比較不會出錯
ctrl+f5 指重新整理 head
Shift 整個網頁重讀
##button
##keyword 有點多看範例程式碼
行動裝置上常用 block 區塊型的
Bs4專屬 啟用跟非啟用狀態 active > 點擊後tago combind呈現 active
Disabled 功能拿掉但外觀一樣
###/RWD/23Button.html
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="MyStyle.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-secondary">Secondary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-danger">Danger</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-light">Light</button>
<button type="button" class="btn btn-dark">Dark</button>
<button type="button" class="btn btn-link">Link</button>
<a href="button" class="btn btn-warning">Warning</a>
<hr />
<button type="button" class="btn btn-outline-primary">Primary</button>
<button type="button" class="btn btn-outline-secondary">Secondary</button>
<button type="button" class="btn btn-outline-success">Success</button>
<button type="button" class="btn btn-warning btn-lg">Warning</button>
<button type="button" class="btn btn-info btn-sm">Info</button>
<hr />
<button type="button" class="btn btn-outline-success btn-block">Success</button>
<button type="button" class="btn btn-warning btn-block">Warning</button>
<hr />
<button type="button" class="btn btn-outline-primary">Primary</button>
<button type="button" class="btn btn-outline-primary active">Primary</button>
<button type="button" class="btn btn-warning disabled" disabled>Warning</button>
<hr />
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input id="Checkbox" type="checkbox" autocomplete="off" /> 沒女友
</label>
<label class="btn btn-secondary">
<input id="Checkbox2" type="checkbox" autocomplete="off" /> 多金
</label>
<label class="btn btn-secondary">
<input id="Checkbox3" type="checkbox" autocomplete="off" /> 位高
</label>
<label class="btn btn-secondary">
<input id="Checkbox3" type="checkbox" autocomplete="off" /> 權重
</label>
</div>
</div>
<script src="Scripts/jquery-3.0.0.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
</body>
</html>
###題外話 Id 在 SEO中 第一個不要寫1 第二個寫2 3 4 這樣排名會高一些
互動就是一種功能一定會用到js
所以屬性要下 data
Data-toggle
最後把網頁介面改寫為行動裝置適合的頁面
###基本操作給base -> btn 然後再給顏色 btn-danger …
按下menu後才會顯示選單
###keyword
Dropdown-menu
Dropdown-item
但是這時只是隱藏 ( 點擊時觸發 所以又是js
data-target
##bs裡面 class 掌管外觀 data 掌控功能
非常多種還是要去bs官網看
##早上的debug
是popper.js函式庫壞掉 ?
結果用cdn引入就好了
結果就用bundle ( 所有的函式庫總庫
結果可以
所以判斷就是poper壞了
偵錯原則
1.f12 console 不能有紅色
2.看DOM
###/RWD/24Dropdown.html
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="MyStyle.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" id="ddMenu1">
Menu
</button>
<div class="dropdown-menu" aria-labelledby="ddMenu1">
<a href="#" class="dropdown-item">Action</a>
<a href="#" class="dropdown-item">Another action</a>
<a href="#" class="dropdown-item">Something else here</a>
<a href="#" class="dropdown-item">Separated link</a>
</div>
</div>
</div>
<script src="Scripts/jquery-3.0.0.min.js"></script>
<script src="Scripts/bootstrap.bundle.min.js"></script>
<!--<script src="Scripts/popper.js"></script>-->
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="Scripts/bootstrap.min.js"></script>-->
<!--<script src="Scripts/bootstrap.bundle.min.js"></script>-->
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>-->
<!--<script src="Scripts/popper.js"></script>-->
<!--<script src="Scripts/bootstrap.min.js"></script>-->
</body>
</html>
下次這個地方會在講一次 ( 講一半
#MVC API 概念
!!!!!!!!!!!!!!!!!!!!!!!!!大重點!!!!!!!!!!!!!!!!!!!!!!!!!!
學會就成為全端工程師 ???
Webserver 不太算 api
現在講的api是 restful
l
程式在哪裡被執行的判斷前後端
但 restfull
夯的原因 可用於異質性設備
UI給人用的介面user interface
API 給程式用的看的介面 給瀏覽器看的 寫一個會看程式的 JAVA or C#
Application INTERFACE
擴充性很高 要盡量寫成 api
XML 階層太多 所以現在流行用 JOSON
API的 Request 是透過 URL
之前都是我們去接 API的資料 JASON
今天我們要當那個 拋的
##API
實作
這個其實有API範本
Global.asax 整個網站的組態 ( 應用程式被執行時會先來這裡
Webapi 與 Route的組態交給這裡
### /07WebAPI/Global.asax
Copy using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Http;
namespace _07WebAPI
{
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// 應用程式啟動時執行的程式碼
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
}
接著看 api 跟 Route的組態
路由設定隱藏路徑 下一次會講
### /07WebAPI/App_Start/RouteConfig.cs
Copy using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace _07WebAPI
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
我們今天先看 api的 ( 路徑一定要依樣
### /07WebAPI/App_Start/WebApiConfig.cs
Copy using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace _07WebAPI
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 設定和服務
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Web.config 給iis看的server的
IQueryable 底層實作都是回復一個集合
差別在於
IEnumerable 抓資料進記憶體
但有時候查詢時 就會不一樣
iv會全抓再去查出來再塞給view
ie會先把查詢linq轉為 tsql command 抓查詢的東西再塞給記憶體
節省記憶體但效能會慢一點
List只能用Ie
所以直接 return 即可 它因為繼承apicontroller 所以不用 return view 因為只會回傳值
要用IHttpActionResult介面
NotFound() 方法丟404
Ok() 方法
失敗error
成功success 200
不用寫 else 因為看到 return就結束了 不然不會結束反而會報錯
沒有view直接編譯候用url呼叫
到webapiconfig.cs 編輯拋出格式
接著用前端呼叫API試試看
用JQ寫AJAX呼叫
寫偵錯 console.log 等等如出錯比較好偵錯
Data.forEach() 把資料利用jason讀的方式讀出來 ( 之前有教 jason的階層) 讀出來
### /07WebAPI/HtmlPage1.html
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<ul id="list">
</ul>
<script src="Scripts/jquery-1.9.1.min.js"></script>
<script>
$.ajax({
type: "GET",
url: "http://localhost:55270/api/Student/",
success: function (data) {
console.log(data);
data.forEach(function (item){
$('#list').append("<li>學號:" + item.學號 + ", 姓名:" + item.姓名 + ", 性別:" + item.性別 + ", 生日:" + item.生日 + ", 電話:" + item.電話 +"</li>");
})
}
});
</script>
</body>
</html>
###安全性問題
必須透過url呼叫 無法直接開啟
###建億的錄影影片
##小結論:
前端就是在寫介接 scrip ( 純前端
拋資料 ( 純後端
Api讓前後端可以完全切開
弄個bs排版之類的應該就是 ( 網頁設計師 ….
接著再回到HtmlPage1.html
##寫前端的jq查詢 ( 只要傳id
雖然是後端要資料 但是 是在後台運作的ajax 所以並不會postback 使用者ux感覺良好
### /07WebAPI/HtmlPage1.html
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<input id="id" type="text" placeholder="請輸入學號" />
<input id="btnGet" type="button" value="查詢" />
<ul id="list">
</ul>
<script src="Scripts/jquery-1.9.1.min.js"></script>
<script>
$.ajax({
type: "GET",
url: "http://localhost:55270/api/Student/",
success: function (data) {
console.log(data);
data.forEach(function (item){
$('#list').append("<li>學號:" + item.學號 + ", 姓名:" + item.姓名 + ", 性別:" + item.性別 + ", 生日:" + item.生日 + ", 電話:" + item.電話 +"</li>");
})
}
});
$('#btnGet').click(function () {
$.ajax({
type: "GET",
url: "http://localhost:55270/api/Student/"+$('#id').val(),
success: function (item) {
console.log(item);
$('#list').empty();
//data.forEach(function (item) {
$('#list').append("<li>學號:" + item.學號 + ", 姓名:" + item.姓名 + ", 性別:" + item.性別 + ", 生日:" + item.生日 + ", 電話:" + item.電話 + "</li>");
//})
}
});
});
</script>
</body>
</html>
以上講的都是讀取
接著三個都是寫進去 增加一筆 既有資料修改 既有資料刪除
複雜隙結法傳整個類別
刪除只要傳id所以不用傳整個類別
這三個都是void 如果要回傳值就可以同時顯示資料庫狀況
填表單通常就要驗證資料 ( 前端會做初步塞選
但前端可能會失誤所以最好還是要防範
( 公開資料通常只會拋資料出來 介接網址跟使用文件 無法寫回去
ModelState.IsValid ( 布林值 )
回傳funtion結構關係所以if 都要先寫反的 ( 如果沒有
Return BadRequest(ModelState);丟錯誤訊息回去
接著如果驗證通過
db.學生.Add(stu);
常犯錯誤 pk 重複或缺少
所以我們就可以把已下放在 try crach
通過才執行db.SaveChanges();
catch(DbUpdateException)
Conflict()將錯誤訊息回傳
如果是沒辦法判斷的例外 利用以下
Throw 把例外直接拋出
Return CreatedAtRoute(“DefaultApi”,new {id=stu.學號});
接著 下一個 既有資料修改
把 新增一筆資料 拿來改即可
驗證如果傳進來的id與stu的學號 不同 拋 badrequest()
db.Entry(stu).State=EntityState.Modified 狀態改成修改
以下相同 最後
要 return statuscode (HttpStatuscode.nocontent);
最後一個 抓學號 然後刪掉
跟查詢資料很像
最後也是return Ok(stu);
後端api至此 ok
回到前端HtmlPage1.html
純前端有壞處 沒razor可以寫所以遇到功能只能寫js
簡單用 bootstrap排版
##Form 不用寫 action 也不用寫 mether 也不用submit 因為都是藉由 ajax
接著
##寫新增的jq方法 ( 只要id
新增type要用post
Request 一定是 url
Data只要呼叫 form id 使用.serialize()資料序列化?(直接幫你把帶的參數寫好的方法
Api / student?學號=s010&姓名=abcd8
這裡又出現bug 可能是jq1.9版本 序列化會怪怪的
結果原來是標籤沒有name所以後端擷取不到
##接著要修改資料 ( 最麻煩 要id又要model
我們把上面的修改一下在查詢時就把資料讀在表單內 ( 原本是獨立在最下面
val() 沒傳參數是取值,有傳參數是給值
##最後是刪除 ( 只要id
跟剛剛新增差不多
整個就是
###/07WebAPI/Controllers/StudentController.cs
Copy using _07WebAPI.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace _07WebAPI.Controllers
{
public class StudentController : ApiController
{
教務系統Entities db = new 教務系統Entities();
// GET: api/Student
public IQueryable<學生> Get()
{
return db.學生;
}
// GET: api/Student/5
public IHttpActionResult Get(string id)
{
學生 stu = db.學生.Find(id);
if (stu == null)
return NotFound();
return Ok(stu);
}
// POST: api/Student
public IHttpActionResult Post([FromBody]學生 stu)
{
if(!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.學生.Add(stu);
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
if(db.學生.Count(s=>s.學號==stu.學號)>0)
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi",new { id=stu.學號},stu);
}
// PUT: api/Student/5
public IHttpActionResult Put(string id, [FromBody]學生 stu)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if(id!=stu.學號)
{
return BadRequest();
}
db.Entry(stu).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
if (db.學生.Count(s => s.學號 == stu.學號) > 0)
{
return Conflict();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// DELETE: api/Student/5
public IHttpActionResult Delete(string id)
{
學生 stu = db.學生.Find(id);
if (stu == null)
return NotFound();
db.學生.Remove(stu);
db.SaveChanges();
return Ok(stu);
}
}
}
###/07WebAPI/HtmlPage1.html
Copy <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link href="Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<form id="form1">
學號:<input id="sid" name="學號" type="text" /><br />
姓名:<input id="name" name="姓名" type="text" /><br />
性別:<input id="gender" name="性別" type="text" /><br />
電話:<input id="tel" name="電話" type="text" /><br />
生日:<input id="birthday" name="生日" type="text" /><br />
<input id="btnAdd" type="button" value="新增" />
<input id="btnUp" type="button" value="修改" />
<input id="btnDel" type="button" value="刪除" />
</form>
<hr />
<input id="id" type="text" placeholder="請輸入學號" />
<input id="btnGet" type="button" value="查詢" />
<ul id="list"></ul>
</div>
<script src="Scripts/jquery-3.4.1.js"></script>
<script>
$.ajax({
type: "GET",
url: "http://localhost:55270/api/Student/",
success: function (data) {
console.log(data);
data.forEach(function (item) {
$('#list').append("<li>學號:" + item.學號 + ", 姓名:" + item.姓名 + ", 性別:" + item.性別 + ", 生日:" + item.生日 + ", 電話:" + item.電話 + "</li>");
})
}
});
$('#btnGet').click(function () {
$.ajax({
type: "GET",
url: "/api/Student/" + $('#id').val(),
success: function (item) {
console.log(item);
$('#list').empty();
//data.forEach(function (item) {
$('#list').append("<li>學號:" + item.學號 + ", 姓名:" + item.姓名 + ", 性別:" + item.性別 + ", 生日:" + item.生日 + ", 電話:" + item.電話 + "</li>");
$('#sid').val(item.學號);
$('#name').val(item.姓名);
$('#tel').val(item.電話);
$('#gender').val(item.性別);
$('#birthday').val(item.生日);
//})
}
});
});
$('#btnAdd').click(function () {
console.log($('#form1').serialize());
$.ajax({
type: "POST",
url: "/api/Student/",
data: $('#form1').serialize()
});
});
$('#btnUp').click(function () {
console.log($('#form1').serialize());
$.ajax({
type: "PUT",
url: "/api/Student/" + $('#sid').val(),
data: $('#form1').serialize()
});
});
$('#btnDel').click(function () {
console.log($('#form1').serialize());
$.ajax({
type: "DELETE",
url: "/api/Student/" + $('#sid').val()
});
});
</script>
</body>
</html>
本機 IIS Webserver 範例 ( 後端會傳這個給前端
##題外話
繫結
###複雜繫結
###簡單繫結
###下一次會講用異質性平台存取同一個api