天天看點

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

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

首先從一個介紹CSS3的國外站點down了一個登入頁(

HTML5+CSS3建構同頁面表單間的動畫切換 ),做了簡單修改後就成了下面這個樣子。
HTML5、CSS3、ASP.NET MVC4 WebAPI大鍋燴
頁面中沒有用到任何圖檔,陰影是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。

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

注意頂部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開頭的不同名方法,但參數一樣,用戶端就會接受到下面這個資訊:

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

這對我這類習慣了一個類裡面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 });      

 運作時出現

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

405 - 用來通路本頁面的 HTTP 謂詞不被允許(方法不被允許)

I know,action預設隻接受Get請求,so我加上[AcceptVerbsAttribute("GET","POST")],重新請求。

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

404的意思是找不到請求的資源,檢視詳細。

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

這種情況估計是參數沒傳到服務端。按照我以往的經驗,應該不會有這種問題。于是我從網上down了幾個大牛的demo,發現皆出現404錯誤,但是看後面的評論,似乎沒有童鞋提出該問題,于是哥糾結了。考慮到前段時間微軟釋出的vs更新包,難道是版本更新導緻傳參方式變動?正打算去找一下官方的更新文檔,一個特性FromBody映入眼簾(

asp.net webapi下json傳值方式

)。我抱着試試看的心情,嘗試了下。

public IEnumerable<ModuleTreeItem> GetUserModules([FromBody] int uid),運作。

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

看到這裡,是不是有種想撞牆的趕腳?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

繼續閱讀