部屬 IIS 注意:Config 繼承

部屬網站的時候,常常碰到幾個問題:這個簡訊網站要部屬在80 Port、還是1234 Port?這個購物網站是要部屬為站台、還是站台下的一支應用程式?前一個問題是 IIS 上做設定就好,但如果是後一個問題,就是部屬的位置有差。

以前常常在想:部屬為站台、還是部屬為站台下的一支應用程式,兩者間除了網站執行的時候,網址差了一層以外,還有什麼差別嗎?曾經的我覺得沒差,直到某一天因為不知道config有繼承關係而在部屬正式環境的時候卡了三小時後,才知道config還是有差的。

預設情況下:子網站的config會繼承根目錄的config設定,即應用程式會預設站台的config設定,如下圖中的SUB網站會預設繼承Default Web Site的config設定。

01_IIS

簡單準備一個MVC網站做測試,單純撈出一個AppSetting設定值顯示到UI上。程式碼如下圖:

02_appSettingCode

 

同樣的程式部屬在Default Web Site、與其下的SUB網站,config的appSettings則先只設定Default Web Site的話,兩者跑出來的結果是一樣的,這就是因為SUB網站預設繼承Default Web Site的config設定。

03_result

雖然說SUB網站繼承Default Web Site的config設定,但也可以在SUB網站的config設定中另外設定該appSettings的值,這樣一來,SUB網站在使用該設定值時,就會讀取自己的設定值。

04_result2

 

接著測試連線字串。稍微調整一下程式碼,多讀一個設定檔,將某一個連線字串顯示出來。

05_connstrCode

如果連線字串只有設定Default Web Site的話,那麼SUB網站自然繼承Default Web Site的設定,進而與Default Web Site顯示一樣的內容;但如果在SUB網站的config設定中另外設定該連線字串,SUB網站卻不是使用自己的設定值,而是整個網站出錯。

06_result3

 

一般情況下,子網站與根目錄有使用同名稱的連線字串,所要連線的資料庫應該都是一樣的。如果真的要分開設定、讓網站各自讀取自己的連線字串,例如因為套用某些模組、或者程式中有使用一樣的 abstruct class,導致無法變更連線字串的名稱等,偏偏又因為正式環境的部屬方式可能無法變更、又得想辦法讓它們分開獨不同的資料庫時,那麼就得讓根目錄的連線字串設定值不被繼承了。

07_configs

※ 上圖左為 Default Web Site 的 config,又為 SUB 網站的 config

 

其實這時候<location>可以派上用場了!<location> 標籤或許不少人會認識,只不過通常都用來設定一個網站中有哪個頁面的設定不同,或許是設定權限、又或者是設定驗證;然而<location>還有一種用法,就是框出config中的設定值不可被繼承。

使用方法如下圖所示,<location> 的標籤中必須定屬性inheritInChildApplications="false"指名不可被繼承設定,至於路徑的部分則設定path="."即可,其中,比較需要注意的事情是<location>標籤必須將「不要被繼承的設定」包起來。

08_configs2

※ 上圖左為 Default Web Site 的 config,又為 SUB 網站的 config

 

由於appSettings中的設定值,原先就可以讓SUB網站讀取自己的設定檔,所以相較於連線字串來說,appSettings不被<location>標籤包起來也無所謂。

如此一來,兩個網站就可以執行出不同的結果了。

09_result4

 

比較有趣的事情是,關於<location>的使用方式並沒有在MSDN網站中找到解釋、也沒有找到這種使用方式,而這一個解法卻是從他人部落格中找到,實驗之後確實是成功、可以使用的,然而為什麼微軟卻沒有相關的文章就不得而知了。

相對的,MSDN網站對於<location>的解釋中卻有 allowOverride 這一個看起來似乎是同功能的屬性,但卻不知道是我沒有搭配好其它設定還是怎樣,無法使用。

 

相關參考:

 

程式環境相關 目錄

1. 在 IIS 上架設 FTP 站台

2. 部屬 IIS 注意:Config 繼承

 

 

 

 

 

 

 

 

end

在IIS上架設FTP站台

2015.10.02

因為某個專案功能需求,所以為了測試、而自己準備了一個 FTP 站台,其中環境為 Windows Server 2012 R2 (in VM)

 

一、架設 FTP 站台

由於是在 Windows Server 的環境,所以 Windows 功能變成伺服器角色及功能 (如下圖):

VMRole01

因應FTP功能而需要勾選啟用的角色及功能就不再此條列,因為小菜鳥本身一來不是很清楚為什麼要勾選、二來因為個人有其他需求所以勾了不少東西(在此不排除因為自已不夠懂),所以有需要的人詳見參考網址:http://my-fish-it.blogspot.tw/2012/09/ss-iis-7-ftp-server.html

小菜鳥是根據客戶環境進行模擬的,所以是在 IIS 上新增一個 FTP 站台:(步驟:IIS > 站台 > 右鍵選取「新增FTP站台」)

 

FTPonIIS

接著輸入站台名稱與對應的檔案路徑,接著在設定繫結時須注意:

1. 一般 FTP 都是採用 21 PORT

2. IP位置不可未指派,需指定為該台機器 IP:原因小菜鳥也不清楚,但不設定的話FTP站台就無法啟動了

最後設定驗證與授權,此處就根據個人需求設定了。

 

二、關於 FTP 站台設定

1. 可於「FTP授權規則」中設定有哪些登入者可使用FTP

2. 可於站台中新增「虛擬目錄」,讓使用者透過 FTP 存取其他資料夾、而不需要被限定於「FTP站台的實體路徑」

 

三、測試 FTP

小菜鳥目前所知方便的測試方式有2種:命令提示字元、以及檔案總管

命令提示字元:

1. 開啟命令提示字元後輸入「ftp ip」

2. 輸入登入  FTP 帳密

FTPcmdlogin

用命令提示字元的好處是:會用command的人後面就可以直接操作了,但說真的……這對小菜鳥來說難度還挺大

不過小菜鳥還是有找到相關網址,有興趣的人可以繼續深究:

1. http://www.nsftools.com/tips/RawFTP.htm#PASV

2. https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes

另一種方式是用檔案總管:

1. 直接在路徑的地方輸入:「ftp://IP/]」或「ftp://IP/[資料夾/]」

2. 輸入帳密後進行登入

ftpFileManager

這種做法的好處是:有UI操作更直覺…… 小菜鳥比較偏愛這種做法就是了

 

參考:

1. http://my-fish-it.blogspot.tw/2012/09/ss-iis-7-ftp-server.html

2. http://www.dotblogs.com.tw/haohao200138/archive/2012/10/27/79106.aspx

3. http://www.nsftools.com/tips/RawFTP.htm#PASV

4. http://www.nsftools.com/tips/RawFTP.htm#PASV

5. https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes

 

JQuery API 條列清單

2015.07.18

在此僅條列基本常用、也是目前所學習到的功能清單:

 

一、Selection

Selectors

  • Derived from CSS Selectors
  • Ex:
    • $(“selector1, selector2, selector N");
    • $(“element[attr=’value’][attr=’value2′]");
    • $(“selector")[0];
    • $(“selector").get(0);
  1. $(“*");
  2. $(“elementName");
  3. $(“#elementId");
  4. $(“.class");
  5. $( “selector[attr]" );
  6. $( “selector[attr=’value’]" );
  7. $( “selector[attr^’value’]" );
  8. $( “selector[attr$’value’]" );
  9. $( “selector[attr*’value’]" );
  10. $(“ancestor descendant");
  11. $(“parent elem > child elem");
  12. $(“prev elem + next elem");
  13. $(“prev sibling + next sibling");
  14. $(“element:first");
  15. $(“element:last");

Filters

  1. $(“:button");
  2. $(“:checkbox");
  3. $(“:password");
  4. $(“:submit");
  5. $(“:text");
  6. $(“:file");
  7. $(“:contains(text)");
  8. $(“:not(selector)");

Chaining

  • $(“selector").method1().method2();

 

二、Manipulating the DOM

Element Manipulation

  1. Modifying Element Data
  • $(“#p").html(“The quick brown fox jumped over the <em>lazy</em> dog);
  • $(“#p").text(“The quick brown fox jumped over the lazy dog);
  • $(“#div p:first").text(“This changes the first paragraph of the #div div);
  1. Modifying Elements
    • $(“content").appendTo(" selector “);
    • $(“content").prependTo(" selector “);
      1. Ex: $(“selector").append(“<li>this is after</li>")
    • $(“content").insertAfter(“selector");
    • $(“content").insertBefore(" selector “);
      1. $(“selector").after(“<li>this is after</li>")
      2. $(selector).before(content, function(index) {} );
  1. Copying Elements
    • $(“selector").clone().appendTo(“selector2″);
  2. Creating New Elements
    • $( “<a/>", {
      html: “This is a <strong>new</strong> link",
      “class": “link",
      href: “page.html"
      });
  3. Removing Elements
  • $(“selector").remove();
  • $(“selector").detach();
  • $(“selector").empty();
  1. Replacing Elements
    • $(“selector").replaceAll(“content")
    • $(“selector").replaceWith(“content")
  2. Wrapping Elements (warp :包含)
    • $(“selector").wrap();
    • $(“selector").wrapAll();
    • $(“selector").wrapInner();
    • $(“selector").unwrap();

Modifying Attributes

  • $(“selector").attr(“name","value");
  • $(“selector").prop(“name","value");
  • $(“selector").removeAttr(“name");
  • $(“selector").removeProp(“prop");
  • $(“selector").attr(“name", function(attr) { … } );

Styling & Dimensions

  1. Style
  • $(“selector").css(“style","value");
  • $(“selector").css({“style":"value","style":"value"});
  • $(“selector").css(“style", function(index, value) { … } );
  1. Class
  • $(“selector).hasClass(“className");
  • $(“selector).addClass(“className");
  • $(“selector).addClass(“className className2″);
  • $(“selector).addClass(“className").removeClass(“className");
  • $(“selector).removeClass(“className");
  • $(“selector).removeClass(“className");
  • $(“selector).toggleClass(“className className2″);
  1. Dimensions
  • $(“selector").width(“100px");
  • $(“selector").width();
  • $(“selector").height(“100px");
  • $(“selector").height();
  • $(“selector").position();

 

三、Events

Attachment and the Event Object

  • .on() and .off()
    • Ex:
      $( “#dataTable tbody tr" ).on( “click", function() {   log( $( this ).text() );    });
  • .bind() and .unbind()
    • Ex:
      $( “#foo" ).bind( “click", function() {    alert( “User clicked on ‘foo.'" );    });
  • .delegate() and .undelegated()
    • Ex:
      $( “table" ).delegate( “td", “click", function() {    $( this ).toggleClass( “chosen" );    });
  • .one()
    • Ex:
      $( “p" ).one( “click", function() { alert( $( this ).text() );   });
  • .live() and .die()
    • Ex:
      var foo = function() { /* Code to handle some kind of event */ };
      $( “p" ).live( “click", foo );
      $( “p" ).die( “click", foo );
  • .trigger() and .triggerHandler()
    • Ex: $( “#foo" ).trigger( “click" );

 

Event Object

  1. Holds all of the event properties

Browser Events

  • .error()
    • Called if an element is not loaded correctly
    • Ex: $( “#book" ).error(function() {
      alert( “Handler for .error() called." )
      })
  • .resize()
    • When the size of the browser window changes
  • .scroll()
    • When the user scrolls to a different place in an element

Document Loading Events

  • .load()
    • When an element is being loaded
  • .ready()
    • When the DOM is loaded and ready (minus content like images)
      Use $(function) as a shortcut
  • .unload()
    • Opposite of load, when an element is being unloaded

Form Events

  • .change()
    • When an element’s value changes
  • .focus()
    • When an element receives focus
  • .blur()
    • When an element loses focus
  • .focusin()
    • When an element or any nested elements receives focus
  • .focusout()
    • When an element loses focus
  • .select()
    • When the user makes a text selection inside
  • .submit()
    • When the user is attempting to submit a form

Keyboard Events

  • .keydown()
    • When a key is pressed down
  • .keypress()
    • When the browser registers keyboard input (may vary by browser!)
      Not triggered by Shift, Esc, delete, etc.
  • .keyup()
    • When a key returns to the up position

Mouse Events

  • .click()
  • .dblclick()
  • .hover()
    • Bind a single handler to the matched elements, to be executed when the mouse pointer enters or leaves the elements
  • .mousedown()
  • .mouseenter()
  • .mouseleave()
  • .mousemove()
  • .mouseout()
  • .mouseover()
  • .mouseup()

 

四、Effects

Basic Effects

  • .hide()
  • .show()
  • .toggle()
    • If it’s showing, hide it. If it’s hiding, show it.

Fading (逐漸透明 / 不透明)

  • .fadeIn()
  • .fadeOut()
  • .fadeTo()
    • Set the opacity to a set value
    • It is similar to the .fadeIn() method but that method unhides the element and always fades to 100% opacity.
  • .fadeToggle()
    • If it’s showing, fade it out. If it’s hidden, fade it in.

Sliding

  • .slideUp()
    • Hides an element using a sliding motion
  • .slideDown()
    • Shows an element using a sliding motion
  • .slideToggle()
    • If it’s showing, then hide it. If it’s hiding, then show it.

Custom Effects

  • .animate()
    • Perform a custom animation of a set of CSS properties
  • .queue(), .dequeue(), and .clearQueue()
    • Control the queue of functions to be executed on the matched elements
  • .delay()
    • Set a timer to delay execution of subsequent items in the queue
  • .stop()
    • Stop the animation
  • .finish()
    • Stop the animation and clear queue

 

五、Ajax and Async

Global Ajax Event Handlers

  • .ajaxSend()
  • .ajaxStart()
  • .ajaxStop()
  • .ajaxComplete()
  • .ajaxSuccess()
  • .ajaxError()

Helper Functions

  • param()
  • .serialize()
  • .serializeArray()

Low-Level Interface

  • $.ajax()
    • Perform an asynchronous HTTP (ajax) request
  • $.ajaxPrefilter()
    • Handle custom ajax options before requests are sent
  • $.ajaxSetup()
    • Set default values for future ajax requests (not recommended)
  • $.ajaxTransport()
    • Allows for ajax transmission of custom data types

Shorthand Methods

  • $.get()
    • Load data from the server using a HTTP GET request
  • $.post()
    • Load data from the server using a HTTP POST request
  • $.getJSON()
    • Load JSON-encoded data from the server using a HTTP GET request
  • $.getScript()
    • Load a JavaScript file from the server using a HTTP GET request and then execute it
  • .load()
    • Load data from the server and place the returned HTML into the matched element

Deferred Object

The Deferred object can register and invoke callback queues and relay the callbacks’ success or failure asynchronously. It can be chained, but is a different object than $.

  • $.Deferred()
  • promise()
  • then() and .done()
  • fail() and .always()
  • $.when()
  • .promise()

 

參考資料:

  1. 微軟MVA網站: https://www.microsoftvirtualacademy.com/en-US/training-courses/introduction-to-jquery-8429
  2. JQuery API 文件: http://api.jquery.com/

Migrations (Code First)

2015年7月

 

其實從 Code First 大道逃跑並不是那麼簡單的一件事情,至少還有守衛在呢!那守衛可是 Code First 大人的左右手,如同大學教授以及其研究助理一般的存在。那麼小菜鳥是如何躲過守衛的防備呢?

小菜鳥:「為什麼要用躲的啊?要打開大門的鑰匙與密碼都在守衛手裡呢。」

作者:「所以我很好奇……你那時候交給守衛的東西是什麼?竟然讓守衛幫你開門……」

小菜鳥:「嘿嘿~因為那時候守衛大人可是急欠了 Migrations 的研究範本嘛,我可是幫了他大忙喔!」

由此可知,逃離 Code First 大道之必備工具:「Migrations」,有人翻譯為資料庫遷移,主要是讓人方便地更改資料庫的 Schema。

所以接下來,就來看看小菜鳥的逃跑工具「Migrations」吧!

 

先準備好資料表的Model、以及DbContext的類別。

小菜鳥一開始只準備了一個 Model 如下:

01_Model

連接資料庫的DataAccess類別:

02_MigrationContext

小菜鳥只在 config中加入了一個連線字串:

03_Config

程式碼執行內容只是加入一筆資料:

04_ExecCode

於是就建立了最初的資料庫:

05_DbVersion1

由於 Migrations 是要透過下 NuGet Command 的方式執行,所以需要開啟 NuGet 管理器主控台(可從「工具」>「NuGet套件管理員」>「套件管理器控制台」進入):

06_NuGetConsole

在下指令之前,記得先把「預設專案」設定為要執行 Migrations 的專案,以小菜鳥的例子來說,就是 TestMigrationEF。

基本上,第一個指令都會是「Enable-Migrations」,先啟用 Migrations 再說吧!一旦啟用之後,專案中會自動增加了 Migrations 的資料夾、Configuration.cs、以及第一個版本的 {XXXXXXXXXXXXXXX}_InitialCreate.cs 檔案。

07_EnableMigrations

作者:「……小菜鳥,你的 Entity Framework 是用哪個版本?」

小菜鳥:「6.1啊,怎麼了?」

作者:「因為我發現你的自動有 _InitialCreate.cs 的檔案了,但網路上的範例沒有說,在想是不是版本差異。」

小菜鳥:「……我不想等 Code First 大人回來、更不想去送死,所以等你有答案的時候在回答我吧。」

作者:「……」

 

先來看一下Configuration.cs,裡面的 Seed 方法,這是當程式把資料庫版本更新到最後一個版本後就會執行的,用來提供塞入預設資料。

08_Seed

再來說說第一個版本的 {XXXXXXXXXXXXXXX}_InitialCreate.cs 檔案吧!打開看就不難發現資料庫的 Schema 已經寫好在裡面了。這裡只會有兩個方法:Up、與Down,分別表示了資料庫升降級即資料庫版本異動時,所要執行的動作;而身為第一個版本的 InitialCreate 自然就是當資料庫建立時所要執行的動作。

09_V1

通常不太需要在這裡做任何修改,但如果有打算調整的話,也可以考慮在此處加入 Index:

10_AddIndex

加了之後,可以嘗試把原先的資料庫刪掉、或者在連線字串中更換資料庫名稱,用以進行重建資料庫;小菜鳥選擇的方法就是後者,直接建一個新的資料庫以檢查是否有一個 Index存在(如果只是單純用 Code First 建立資料庫的話,Entity Framework預設是不會幫忙建立 Index 的)、並檢查是否有預設資料。

準備好後,就下指令:「Update-Database」以建立資料庫或版本更新。

11_UpdateDbCmd

12_IndexInNewDB

 

接著來異動一下 Schema 吧!

小菜鳥很簡單地又加入了第二個資料表的 Model去做關聯原先的第一個資料表:

13_AddTable

14_AddRelation

接著,小菜鳥就下指令:「Add-Migration InitialCreate」,於是就可以看到第二個版本的 {XXXXXXXXXXXXXXX}_InitialCreate.cs 檔案。

15_V2

作者:「然後你就要執行 Update-Database 了嗎?」

小菜鳥:「當然,不然我要怎麼更新Schema。」

作者:「……我先等等看有沒有好戲發生好了。」

小菜鳥:「為什麼要這樣說?!你這樣給我一種不安的預感耶!」

作者:「我先泡茶好了,等等你哀哀叫完還可以潤喉一下。」

小菜鳥:「……什麼意思嘛!」

結果證明,小菜鳥執行「Update-Database」是失敗的,失敗原因倒是有顯示出來:「System.Data.SqlClient.SqlException (0x80131904): ALTER TABLE 陳述式與 FOREIGN KEY 條件約束 “FK_dbo.Employees_dbo.Departments_DepId" 衝突。衝突發生在資料庫 “MigrationEF2″,資料表 “dbo.Departments", column ‘Id’。」

小菜鳥哭喪著一張臉:「作者……為什麼啊……」

作者:「不意外吧?原先又沒有 Department 資料、甚至連資料表都沒有,你又限制 Employee 一定要對應到 Department,那目前在資料庫中的那筆資料怎麼辦?」

小菜鳥:「對吼!」

 

於是小菜鳥先把關聯拿掉,包含 Employee 中的 department、與 DepId,Department 中的 employee;並手動調整每次版本更新Up方法。

首先,第二個版還不可以加入關聯,所以第二個版本小菜鳥就讓 Migrations 只執行加入 Department 資料表:

16_NewV2

並讓Seed方法中加入一筆資料:

17_NewSeed

這樣一來就可以成功執行「Update-Database」了。

18_UpdateDbCmd2

 

接著再把之前拿掉的關聯還原、再加入一個版本,讓第三個版本執行加入關聯以及欄位,記得讓 Foreign Key 有一個預設值(須確認資料庫中有一筆 Department 資料、且 Id 為預設值),否則可能會因為舊的資料沒有預設值導致失敗。

19_V3

然後才下指令「Update-Database」。

20_UpdateDbCmd3

21_DB

 

值得一提的是,大家可以觀察一下 __MigrationHistory 這個資料表,它會記錄著每一次的版本更新。

22_VersionHistory

 

作者:「所以說~ 大家要先等小菜鳥全部做完、好戲看完之後再來學習 Migrations 喔!」

小菜鳥:「……所以說,為什麼你不要再一開始的時候就先提醒我嘛!」

作者微微一笑:「有好戲看我為啥不看?」

小菜鳥:「……作者你是壞人!!!」

《完》

 

《其他說明》

在小菜鳥「Update-Database」失敗的時候,其實亂嘗試了很多次的「 Add-Migration InitialCreate 」、與「Update-Database」,所以曾經重複把資料庫的版本紀錄即 __MigrationHistory 中的資料進行刪除調整,所以文中的 第二次之後的 「Update-Database」結果截圖是有點錯誤的,因為少了 Running Seed method. 這一行指令。

正確的「Update-Database」結果應該如下:

23_RightUpdateCmd

也因此,小菜鳥得到了幾個結論:

  1. Migrations 的最後版本應該是有紀錄的(但還不清楚記錄到哪裡);沒有執行到最後版本的 Migrations  就不會執行 Seed 方法
  2. 刪除 __MigrationHistory  中的資料會影響 Migrations  對版本的判斷;例如說:目前總共三個版本,只要把 __MigrationHistory 調整到只有版本一的紀錄,那麼 Migrations  執行的時候就會從版本二的 Up 方法開始執行

 

《簡單 NuGet Migration 指令條列》

  1. get-help EntityFramework:取得指令說明
  2. Enable-Migrations:啟用 Migration
  3. Add-Migration:小菜鳥個人建議使用文中的範例「Add-Migration InitialCreate」,雖然這有點毫無根據,因為只是純粹的小菜鳥的個人經驗+對成功率高低的感覺
  4. Update-Database:針對 config 中的連線字串進行更新資料庫版本
  5. Get-Migrations:顯示目標資料庫的版本紀錄

 

補充相關參考:

  1. Migrations in MVC:http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/migrations-and-deployment-with-the-entity-framework-in-an-asp-net-mvc-application
  2. Code First Migrations:https://msdn.microsoft.com/en-us/data/jj591621.aspx
  3. Migrations(資料庫遷移):http://guides.ruby.tw/rails3/migrations.html
  4. Entity Framework Nuget Console commands:http://stackoverflow.com/questions/12261799/entity-framework-5-nuget-console-commands

 

MVC世界遊(1) – 導覽

2015年04月07日

因應公司專案打算採用 MVC 開發,所以開始在線上參與微軟的 MVA 課程:

http://www.microsoftvirtualacademy.com/training-courses/introduction-to-asp-net-mvc

說真的,在這之前為了支援另一個專案,我就已經先用 MVC 寫過一次了…… (雖然第一次碰 MVC 寫得非常的爛 QAQ)

正好趁這次上課可以邊做筆記了,順便回頭惡補一下之前沒有學的基礎知識……Orz.

 

一、什麼是 MVC

MVC 指的是軟體架構,我個人覺得可以稱之為某一種專案設計的理念或說是精神的落實;簡單地理解,就是將一個系統拆解成 M、V、C 三個大區塊。

那「M」、「V」、「C」分別指的是什麼?只要隨便上網查一下都可以查到:

  • M = Model:中文翻譯為模型
  • V = View:中文翻譯為檢視、或是視圖,圖形介面設計
  • C = Controller:中文翻譯為控制器,負責轉發請求、對請求進行處理,簡言之就是負責邏輯處理的部分

說實話,以我第一次碰 MVC 的經驗來說,我個人覺得這些解釋雖然可以讓人分別知道 M、V、C,但 MVC 組合起來之後,我還是不知道怎麼開始做 MVC……(Orz)

嘛,在這時候我會很支持以前看過的一句話:Coding就是從動手開始,看了一大堆不如動手寫了一大堆。

 

二、從 Request 到 Response

【其實伺服器就像個工廠,負責將材料轉變成產品輸出】

課程影片中講到這一段時只有短短的幾分鐘,但讓我覺得十分地有價值,因為這是一段可以讓人徹底了解 MVC 到底在做什麼。

以下是簡單的一個流程圖:

我對此的理解是:

Model 是指整個網頁在處理過程(從 Request 到 Response)中用以溝通、傳遞的資料模型;在 C# 中 Model 是一個 Class,而 Class 裡面就可以包含對這些資料的一些處理,我想這也是有一些網頁會將 Model 的解釋為資料的處理方法的原因。

Controller 是負責接收 Request 、並對 Request 進行處理的部分,程式中大多數的邏輯處理也都在這裡;指是當 Request 處理好後、要產生的 Response 會是以 Model 的形式呈現,因為對 Controller 而言,它只負責將 input 的 Request 處理成 Output 的 Model,而 Output 的形式並不在它的負責範圍內。

View 則是對 Controller 的產出進行作最後的轉換,即對 Model 轉為 Html,因此從中文翻譯的檢視、或視圖中就不難發現,View 其實就是負責做視覺上的處理。

 

三、默認的規則

【如同玩遊戲就得遵守遊戲規則】

在 MVC 的運作過程中,有幾項是默認的規則須注意,雖然有些是可以手動進行調整,但是通常都會建議大家直接採用默認的規則來運作。

1. 網址的意義:Url 裡面的 Path 會先對應了 Controller 的名稱、接著是 Controller 的 Action 名稱,接著才會其他參數;不過也可以利用 Route 進行設定。

2. Controller 與 View 的對應:每一個 Controller 要將結果交給 View 進行轉換成 Html,此時 Controller 就會去尋找 Views 資料夾底下的「Controller 名稱的資料夾」中的 .cshtml 檔 ( 若語言為 VB 則是 .vbhtml ),而 Controller 的 Action 名稱則對應了 .cshtml 檔的名稱

 

 

 

MVC 的世界觀── 我想以軟體架構、以及處理流程(從 Request 到 Response )來說就先這樣了。

當時課程中包含使用了 Entity Framework 的 Code First,但我個人覺得 MVC 歸 MVC、Entity Framework 歸 Entity Framework,雖然兩者在過程中都有使用所謂的 Model,但我個人覺得所謂的 Model 只是一個 Class、一個資料的模型、甚至於可以理解為一種資料結構。

若說 MVC 中,Model 只是用來溝通的資料模型(資料結構)、用來與「頁面」溝通的資料模型(資料結構),那麼 Entity Framework 則是用 Model 來與「資料庫」溝通/映射的資料模型(資料結構)。

因此在我的 MVC 的筆記中,就不打算混入了 Entity Framework 的 Code First 了。雖然不管怎樣,Model 都只是一個 Class,但畢竟溝通的對象不一樣、就避免讓大家混淆了;但相對來說,課程影片中在使用 MVC 的同時也採用了 Code First,這在 Visual Studio 中提供了簡單的操作以建立資料庫,大家可以到課程影片中欣賞── 這是在我的文章中不會提到的東西。

 

 

相關參考:

  1. http://zh.wikipedia.org/wiki/MVC
  2. http://www.asp.net/mvc
  3. http://www.microsoftvirtualacademy.com/training-courses/introduction-to-asp-net-mvc

 

EventValidation (番外)

《番外小劇場》

小菜鳥:「嗯?已經沒事啦!HiddenField 你還待在這做啥?」

HiddenField:「……我說,叫我過來幫忙,沒酬勞、沒下午茶的,對嗎?!」

小菜鳥:「想太多了好嗎?」

HiddenField 挑眉,「你不怕我以後都不幫你保存好 __EVENTVALIDATION 的資料?」

小菜鳥:「啊?我沒有在用那種東西啊……嘛,不保存就別保存啊,感覺無所謂啊。」

然後……

小菜鳥:「HiddenField 大人,請問您想吃蛋糕、餅乾、還是巧克力?需要咖啡還是奶茶請盡管吩咐好嗎?」

HiddenField:「哼哼~」

 

簡單地說,頁面上存在一個名為 __EVENTVALIDATION 的 HiddenField,只要這個 value 值給清空的話,就一定會得到 EventValidation 的錯誤了。

08_EVENTVALIDATION

 

作者雙手合十:「所以說啊,小菜鳥,自作虐、不可活啊!」

《劇終》

關注

有新文章發表時,會立即傳送至你的收信匣。