SQL 數值對應 .NET Framework 數值

在ASP.NET MVC中使用Google地圖(Visual Basic版本)

阿源哥哥有發表過一篇「在ASP.NET MVC中使用Google地圖」,我改寫為VB版本。

首先,你必須去申請Google API Key;

在「模組」中撰寫VB的延伸方法;
Imports System.Runtime.CompilerServices
Imports System.Web
Imports System.Web.Configuration
Imports System.Web.Helpers

Public Module GoogleMapExtension

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="helper">擴充型別</param>
    ''' <param name="address">地址</param>
    ''' <param name="mapWidth">寬度</param>
    ''' <param name="mapHeight">高度</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Extension()>
    Public Function GoogleMap(helper As HtmlHelper, address As String, mapWidth As Integer, mapHeight As Integer) As MvcHtmlString
        Dim mapHtml = New StringBuilder()

        mapHtml.Append("<div id=""map"" style=""width:" & mapWidth.ToString() & "px; height:" & mapHeight.ToString() & "px""></div>")
 
        mapHtml.Append("<script src=""http://maps.google.com/maps?file=api&v=2&key=""" & WebConfigurationManager.AppSettings("GoogleMapApiKey") & "\"" type=""text/javascript""></script>")

        mapHtml.Append("<script type=""text/javascript"">")
        mapHtml.Append("var geocoder;")
        mapHtml.Append("var map;")
        mapHtml.Append("var address = '" & address & "';")
        mapHtml.Append("map = new GMap2(document.getElementById(""map""));")
        mapHtml.Append("map.addControl(new GLargeMapControl());")
        mapHtml.Append("map.addControl(new GMapTypeControl());")
        mapHtml.Append("geocoder = new GClientGeocoder();")
        mapHtml.Append("geocoder.getLocations(address, addToMap);")
        mapHtml.Append("function addToMap(response) {")
        mapHtml.Append("place = response.Placemark[0];")
        mapHtml.Append("point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);")
        mapHtml.Append("map.setCenter(point, 13);")
        mapHtml.Append("marker = new GMarker(point);")
        mapHtml.Append("map.addOverlay(marker);")
        mapHtml.Append("marker.openInfoWindowHtml(place.address);")
        mapHtml.Append(" }")
        mapHtml.Append("</script>")

        Return MvcHtmlString.Create(mapHtml.ToString())
    End Function

End Module

在使用要使用的View中,引用Namespage,然以使用以下指令傳入相關參數即可。
<%: Html.GoogleMap(ViewBag.Address, 400, 350)%>

上面的程式碼,被Blog用亂了,請直接看檔案。

ASP.NET MVC 3, 在Visual Studio 2010 Express中玩NUnit

在Visual Studio 2010之中,只有蟹老闆等級(錢錢)付費版本才測試功能,如果你是使用Visual Studio 2010 Express版本,那很抱歉,些版本不支援,請先付錢在說。

那有沒有不付錢的方法,有,請看 ASP.NET MVC Video Training from Pluralsight 第一篇 Introduction 裡教。

環境確認:Visual Studio 2010 Service Pack 1

設定NUnit測試環境

  1. 以下為Visual Basic for ASP.NET MVC 3 Test專案實作步驟:
  2. 在原始專案中,加入一個「類別檔專案」;
  3. 使用 NuGet 加入 「NUnit」,指令為「Install-Package NUnit」,我的版本號為「2.5.10.11092」,等一下會用到,請依安裝的版本號修變改下面資訊。
  4. 加入原始專案的參考。
  5. 修改類別檔專案中,預設 Class1.vb 的檔案,我們要測試的是 HomeController ,那就命名為 HomeControllerTests ,後面加上 Tests。
  6. 在 HomeControllerTests.vb 中,「Imports NUnit.Framework」,另在「Public Class HomeControllerTests」中,加上「<TestFixture()>」屬性。
  7. 新增方法,例如,「Public Sub Puts_Message_In_ViewBag() ... 」,加上「<Test()>」屬性。
  8. 修改原專案裡 HomeController 的 Index Action,把回傳型別修改為 「ViewResult」。你回傳什麼型別,就改為什麼型別。
  9. 在測試方法中新增程式碼。 
  10. 將原始專案及測試專案「建置」。

Imports NUnit.Framework

''' <summary>
''' 測試類別
''' </summary>
<testfixture()>
Public Class HomeControllerTests

    ''' <summary>
    ''' 測試方法
    ''' </summary>
    <test()>
    Public Sub Puts_Message_In_ViewBag()
        ' HomeController 物件
        Dim controller = New HomeController()
        ' 取得物件 Index() 的結果
        Dim result = controller.Index()
        ' Assert 測試 Index 結果裡的 ViewBag.Message 不是空的
        Assert.IsNotEmpty(result.ViewBag.Message)

    End Sub

End Class

這樣就完成整個測試專案。


執行NUnit測試


讓開啟 CMD.exe ,進行到原始專案目錄下,能發現有一個「packages」目錄,讓我們順著目錄走進去「D:\dev\OdeToFood\packages\NUnit.2.5.10.11092\tools」,進到 tools 目錄後,有兩個指令:

nunit.exe :會啟動 GUI 介面程式
nunit-console.exe :文字介面程式

先在 tools 目錄下執使以下指令「D:\dev\OdeToFood\packages\NUnit.2.5.10.11092\tools>nunit-console.exe ..\..\..\OdeToFood.Tests\bin\Debug\OdeToFood.Tests.dll」,意思很簡單,就是執行那個一測試專案。等一下,就能看到執行結果。

例如:

NUnit version 2.5.10.11092
Copyright (C) 2002-2009 Charlie Poole.
Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
Copyright (C) 2000-2002 Philip Craig.
All Rights Reserved.

Runtime Environment -
   OS Version: Microsoft Windows NT 6.1.7601 Service Pack 1
  CLR Version: 2.0.50727.5446 ( Net 2.0 )

ProcessModel: Default    DomainUsage: Single
Execution Runtime: Default
.
Tests run: 1, Errors: 0, Failures: 0, Inconclusive: 0, Time: 0.980056 seconds
  Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0

我們測試結果 Errors: 0,測試成功了。你可以修改原始專案 ViewBag.Message2 ,把變數名稱多加個 2 ,重新建置專案,結果出現:

NUnit version 2.5.10.11092
Copyright (C) 2002-2009 Charlie Poole.
Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
Copyright (C) 2000-2002 Philip Craig.
All Rights Reserved.

Runtime Environment -
   OS Version: Microsoft Windows NT 6.1.7601 Service Pack 1
  CLR Version: 2.0.50727.5446 ( Net 2.0 )

ProcessModel: Default    DomainUsage: Single
Execution Runtime: Default
.F
Tests run: 1, Errors: 1, Failures: 0, Inconclusive: 0, Time: 1.0290589 seconds
  Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0

Errors and Failures:
1) Test Error : OdeToFood.Tests.HomeControllerTests.Puts_Message_In_ViewBag
System.Reflection.AmbiguousMatchException : 多載解析失敗,因為沒有公用 'IsNotEmpty' 對這些引數而言是最適合的:
    'Public Shared Sub IsNotEmpty(collection As System.Collections.ICollection)':
        不是最特定。
    'Public Shared Sub IsNotEmpty(aString As String)':
        不是最特定。
   於 Microsoft.VisualBasic.CompilerServices.OverloadResolution.ResolveOverloadedCall(String MethodName, List`1 Candidates, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, BindingFlags LookupFlags, Boolean ReportErrors, ResolutionFailure& Failure)
   於 Microsoft.VisualBasic.CompilerServices.OverloadResolution.ResolveOverloadedCall(String MethodName, MemberInfo[] Members, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, BindingFlags LookupFlags, Boolean ReportErrors, ResolutionFailure& Failure)
   於 Microsoft.VisualBasic.CompilerServices.NewLateBinding.ResolveCall(Container BaseReference, String MethodName, MemberInfo[] Members, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, BindingFlags LookupFlags, Boolean ReportErrors, ResolutionFailure& Failure)
   於 Microsoft.VisualBasic.CompilerServices.NewLateBinding.CallMethod(Container BaseReference, String MethodName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack, BindingFlags InvocationFlags, Boolean ReportErrors, ResolutionFailure& Failure)
   於 Microsoft.VisualBasic.CompilerServices.NewLateBinding.ObjectLateCall(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack, Boolean IgnoreReturn)
   於 OdeToFood.Tests.HomeControllerTests.Puts_Message_In_ViewBag() 於 D:\StudyTest\OdeToFood\OdeToFood.Tests\HomeControllerTests.vb: 行 19 

出現 Errors: 1,而且還很明確的說是錯在第幾行。

設定NUnit與Visual Studio 2010結合


前面的用法,很不方便,每次都要開CMD而且還要Key一大堆路徑。讓我們使 nunit-console.exe 來與 Visual Studio 2010 結合使用。

測試專案 → 屬性 → 編譯 (這裡的畫面與影片不同)


在「建置後進行編輯」→ 巨集 →

「$(SolutionDir)\packages\NUnit.2.5.10.11092\tools\nunit-console.exe $(TargetPath)」

$(SolutionDir) 為 D:\dev\OdeToFood\
$(TargetPath) 為 D:\dev\OdeToFood\OdeToFood.Tests\bin\Debug\OdeToFood.Tests.dll

按「確定 * 2」即完成。

重新「建置」測試專案。你就能在「輸出」看見測試結果。


當然,以上使用NUnit不只是在Express才能使用,錢錢版,一樣能用。

ASP.NET MVC 3.1 使用Scaffold產生Controller, Action與View

在ASP.NET MVC中,如果你是Model First或Database first,那可以使用Scaffold ( 它就像使用樣版來產生程式架構)來加速你MVC程式的開發。在 ASP.NET MVC 3.1 (等一下我們解釋) 中透過與 Entity Framework 的合作,再加上Scaffold,我們不只可以產生Controller, Action,連View 都可以一併產生,而且是一個可完整使用CRUD程式。如果你的Model或Batabase設計的很好,使用ASP.NET MVC 3.1的Scaffold功能,是有可能連一行程式都不用寫就可以產生一個網站。

參考:Julie的「MVC3.1 Scaffolding Magic with Database (or Model) First , Not Just Code First」(MVC 3.1是從這裡來的)

我的步驟和他一點點不同:(以Visual Basic and Northwind為例)
  1. 產生ASP.NET MVC 3專案
  2. 加入新專案,類別庫
  3. 在類別庫中,新增「ADO.NET 實體資料模型」,依序產生 *.edmx
  4. 由 *.edmx 產生 DbContext ( *.tt )
  5. 回到ASP.NET MVC 3專案,將 app.config 的連線字串複製到 web.config
  6. 參考「類別庫」專案
  7. 到 Controllers 目錄,新增控制器
  8. 修改Global.asax,將 .controller = "Home" 修改為你想要的 Controller,例如,.controller = "Employees"
  9. Ctrl + F5

如果你要使用 ASP 或 ASP.NET 花CRUD就要花費你多少時間,使用使用ASP.NET MVC 的 scaffold 功能,可以快速幫我產生所有 CRUD 的 controller, action, view,讓我們花更少的力氣可以做更多的事。

ASP.NET MVC 基本開發流程

1. Database 規劃( 3NF / BCNF ) --> 2. Model 產生 ( *.edmx / *.tt ) --> 3. 設計Controller / Action --> 4. View

1. Database 規劃( 3NF / BCNF )

我走的是Database First,所以把資料庫放在第一順位。如果你是Model First或Code First,請自行調整。
快速正規化入門:
  1. 1NF:單值。
  2. 2NF:PFD;R(X, Y, Z, A),X --> Y, Z,A不能被X決定,A為PFD。
  3. 3NF:非PK,不存在FD;R(X, Y, Z, A, B),X -->Y,Z,A,B;A --> B;A為非Key,但能決定B。
  4. BCNF:R中所有「決定屬性(唯一性)」均為CK。R(X, Y, Z, A, B), X,Y --> Z,A,B;A --> B;A非CK,但能決定B。

2. Model 產生 ( *.edmx / *.tt )

這部份很簡單與複雜。
簡單的是,百分之百都是由工具產生。複雜的是,*.edmx、*.tt這些檔案內容。

3. 設計Controller / Action

Controller只是命名,比較有關係是Routing。大部份時間都是在寫Action。
Action做三件是:
  1. DataBinding 設定
  2. 驗證資料
    1. Bind 屬性設定
    2. DataAnnotations 的Class設定
  3. 撰寫程式碼

4. View

當資料由Action傳送過來,我們要如何「顯示」。