今日閑來無事,把玩了下傳說中的HTML5、CSS3、ASP.NET MVC4,以及随之釋出的WebAPI。不得不說,新鮮的知識點太多了,不可能按部就班地去學。參照網上的幾篇文章,邊看邊做,搭建了一個簡單的demo,現将一些要點記錄下來。
首先從一個介紹CSS3的國外站點down了一個登入頁(
HTML5+CSS3建構同頁面表單間的動畫切換 ),做了簡單修改後就成了下面這個樣子。
1 <label for="username" data-icon="u">使用者編号</label>
2 <input id="username" name="userCode" required="required" type="text" />
生成圖示的CSS:
1 [data-icon]:after {
2 content: attr(data-icon);
3 font-family: 'FontomasCustomRegular';
4 color: rgb(106, 159, 171);
5 position: absolute;
6 left: 10px;
7 top: 35px;
8 width: 30px;
9 }
其中'FontomasCustomRegular'就是圖示字型。
注意,如果将上面代碼中的label設為不可見,那麼相應的僞類元素也将不可見,因為僞類元素其實仍是目标元素(這裡是label)的子元素(内容);input 不支援僞類元素,因為input無法容納其他元素。
難點在于怎麼樣讓登入區域垂直居中。要實作垂直居中,以前除了寫JS,沒有其它更好的辦法(還可參考
登陸頁面怎麼讓DIV垂直居中,還要相容)。CSS3帶來了flexbox的概念,能讓其中的子元素靈活地排版布局。這裡我們定義外圍容器的樣式,讓它作為flexbox,登入區塊就是它的子元素。
1 #container {
2 width: 100%;
3 height: 100%;
4 position: absolute;
5 left: 0;
6 top: 0;
7 background: url("bg.jpg");
8 display: -webkit-box;
9 -webkit-box-align: center;
10 display: -moz-box;
11 -moz-box-align: center;
12 -moz-box-pack: center;
13 display: -o-box;
14 -o-box-align: center;
15 display: -ms-box;
16 -ms-box-align: center;
17 display: -ms-flexbox;
18 -ms-flex-align: center;
19 }
為了實作垂直居中,我查閱了一些資料,當時就有點怒了。本質同樣的東西,不同廠商非得搞一套自己的命名規則。上述代碼在IE與Chrome中工作預期,但在Firefox中則沒有成功,原因未知。關于flexbox的詳細講解請看
深入了解 Flexbox 伸縮盒模型,需要注意的是現行的一些概念并非所有浏覽器都支援,CSS3距離統一标準還有很長的路要走。
驗證通過後轉到主界面,我們用localStorage.setItem("UserID", "@Model.ID");儲存登入使用者的ID。
注意頂部bar,退對外連結接靠右顯示。在以前,我們用“float:right”就搞定了,但這裡沒起作用,推測由于這個bar是flexbox。後來我将退對外連結接設定成“margin-left:auto”,解決。左側菜單我用WebAPI擷取資料。
1 public class AccountController : ApiController
2 {
3 /// <summary>
4 /// 根據使用者ID擷取有權限的功能子產品
5 /// </summary>
6 public IEnumerable<ModuleTreeItem> GetUserModules(int uid)
7 {
8 var modules = UserLogic.ModuleProcessOfUser(uid);
9 return RoleVM.ChangeSysModuleToTreeItem(modules);
10 }
11 }
關于擷取資料和構造樹的細節和本主題無關,略之。按照WebApi(這裡指的就是Asp.Net MVC4 WebApi,下同)的預設約定,現在可以用api/Account?uid=1(不能直接api/Account/1,因為參數名如果不是路由規則預設的話,需要顯式指定)請求該資源了。(讀者:啥,你說資源?GetUserModules這個action哪去了?)WebApi遵照Restful風格,在Rest中,任何對服務的請求都是針對資源的,請求類型包括增删改查。這裡Account就是資源,當服務端接收到Get請求時,會查找以“Get”開頭的action并比對參數,這裡就比對到了GetUserModules,POST\DELETE\PUT的路由方式同理。如果有多個Get開頭的不同名方法,但參數一樣,用戶端就會接受到下面這個資訊:
這對我這類習慣了一個類裡面N多方法的人來說,相當不習慣。我想既然Rest沒有action這個概念,那麼我将所有的action都轉為controller的形式,作為資源暴露出去,不過這種方式也同樣别扭。于是我增加了一個路由規則:
1 config.Routes.MapHttpRoute(
2 name: "ActionApi",
3 routeTemplate: "api/{controller}/{action}/{id}",
4 defaults: new { id = RouteParameter.Optional }
5 );
後記:在ASP.NET MVC4中,web api預設就支援api/{controller}/{action}模式,不需要顯式增加該路由規則。
雖然違背了rest的原則,但我想凡事不能照本宣科,新的路由規則既然不會帶來什麼壞處,為什麼不用呢?此時咱們就可以用api/Account/GetUserModules?uid=1來請求了。接着我輕快地敲出JS調用代碼。
1 var requestData = JSON.stringify({ uid: localStorage.getItem("UserID") });
2 $.ajax({
3 url: '/api/Account/GetUserModules',
4 data: requestData,
5 type: "post",
6 dataType: "json",
7 contentType: "application/json; charset=utf8",
8 success: function (data) {
9 var inline = new kendo.data.HierarchicalDataSource(
10 {
11 data: data,
12 schema: {
13 model: {
14 children: "Children"
15 }
16 }
17 });
18 $("#treeview").kendoTreeView({
19 dataSource: inline,
20 dataTextField: ["Module.Name"]
21 });
22
23 }
24 });
運作時出現
405 - 用來通路本頁面的 HTTP 謂詞不被允許(方法不被允許)
I know,action預設隻接受Get請求,so我加上[AcceptVerbsAttribute("GET","POST")],重新請求。
404的意思是找不到請求的資源,檢視詳細。
這種情況估計是參數沒傳到服務端。按照我以往的經驗,應該不會有這種問題。于是我從網上down了幾個大牛的demo,發現皆出現404錯誤,但是看後面的評論,似乎沒有童鞋提出該問題,于是哥糾結了。考慮到前段時間微軟釋出的vs更新包,難道是版本更新導緻傳參方式變動?正打算去找一下官方的更新文檔,一個特性FromBody映入眼簾(
asp.net webapi下json傳值方式)。我抱着試試看的心情,嘗試了下。
public IEnumerable<ModuleTreeItem> GetUserModules([FromBody] int uid),運作。
看到這裡,是不是有種想撞牆的趕腳?400,錯誤請求。檢視詳細資訊:{"Message":"請求無效。","MessageDetail":"對于“WebHabilimentERP.API.AccountController”中方法“System.Collections.Generic.IEnumerable`1[SysProcessViewModel.ModuleTreeItem] GetUserModules(Int32)”的不可以為 null 的類型“System.Int32”的參數“uid”,參數字典包含一個 null 項。可選參數必須為引用類型、可以為 null 的類型或聲明為可選參數。"}。
經過一番google、bing,甚至百度都上場了,終于找到一篇稍微有用的文章:
ASP.NET WebAPI throw 404 if method parameter is string or int。按照文中方法嘗試,無果。不過它倒提醒我,是不是不用傳參數名,既将data: { uid: localStorage.getItem("UserID") }改為data: localStorage.getItem("UserID"),成功。
最終代碼如下:
服務端
1 [AcceptVerbsAttribute("GET","POST")]
2 public IEnumerable<ModuleTreeItem> GetUserModules([FromBody] int uid)
3 {
4 var modules = UserLogic.ModuleProcessOfUser(uid);
5 return RoleVM.ChangeSysModuleToTreeItem(modules);
6 }
用戶端
1 $.ajax({
2 url: '/api/Account/GetUserModules',
3 data: localStorage.getItem("UserID"),
4 type: "post",
5 dataType: "json",
6 contentType: "application/json; charset=utf8",
7 success: function (data) {
8 var inline = new kendo.data.HierarchicalDataSource(
9 {
10 data: data,
11 schema: {
12 model: {
13 children: "Children"
14 }
15 }
16 });
17 $("#treeview").kendoTreeView({
18 dataSource: inline,
19 dataTextField: ["Module.Name"]
20 });
21
22 }
23 });
敲門(非入門)完畢。
關于Post參數值傳不到背景的補充連接配接:
Web.API and jQuery JSON Post- null value?轉載請注明出處:
http://www.cnblogs.com/newton/archive/2013/04/25/3043615.html