HTML5、CSS3、ASP.NET MVC4 WebAPI大鍋燴


今日閑來無事,把玩了下傳說中的HTML5、CSS3、ASP.NET MVC4,以及隨之發布的WebAPI。不得不說,新鮮的知識點太多了,不可能按部就班地去學。參照網上的幾篇文章,邊看邊做,搭建了一個簡單的demo,現將一些要點記錄下來。

首先從一個介紹CSS3的國外站點down了一個登錄頁(HTML5+CSS3構建同頁面表單間的動畫切換),做了簡單修改后就成了下面這個樣子。 

頁面中沒有用到任何圖片,陰影是CSS3新加的渲染標記,文本框中的圖標乃是一種字體,這里還用到CSS中偽類的東東。比如用戶編號和對應文本框的html:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM