2012年5月30日 星期三

使用非管理員權限來部署 ASP.NET 應用程式

系統交付給客戶後,系統是有保固時間的。當程式有 bug,就需要更新程式。如果程式更新都要請客戶自己部署,那之後就要讓客戶使用起來方便。
而要請使用管理員權限來部署 ASP.NET 應用程式,就很可能被質疑,如果客戶程度夠的話。

因此需要一個可以使用非管理員權限來部署 ASP.NET 應用程式的方式。

目前使用 IIS 7.

建立更新帳號

只需要一般帳號即可。以下以 smartDeployer 為例

image

安裝/設定 IIS

如果沒有安裝 IIS,就照著下圖做。如果已經安裝了,就要看看哪些功能未被勾選。

image

image

 

image

image

Web Management Server 是一定要裝的。上圖少勾選了。Windows Authentication 不用裝(上圖有誤) 。

image

安裝 .NET Framework 4.0

記得安裝  .net framework 4.0 及  sp1。如果需要的話

安裝 Web Deploy tool V2.1

我們靠的就是 Web Deploy Tool,目前的版本是 2.1。記得在要部署的伺服器上,要完整安裝。

image

設定 Web Management Service

clip_image002

Web Management Server 必須靠 Basic 驗證。故需要啟用。

clip_image003

clip_image005

檢查 Enable remote connections (1)是否已經勾選(應已勾選)。若沒有勾選,請先按右方的「Stop」(2)鍵後,勾選「Enable remote connections」 ,再 Start(3)鍵。

clip_image007

授權

我們要授權 smartDeployer 可以在 Default Web Site 更新

clip_image009

clip_image010

最後按 Setup

clip_image011

防火牆

記得打開防火牆,port  8172

以上就完成了網頁伺服器的設定

部署

使用 Visual Studio 2010 打包後的 指令不能用。經明察暗訪後,需修改指令如下

"C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\\msdeploy.exe" -source:package='Package.zip' -dest:auto,computerName='https://serverNameOrIp:8172/MSDeploy.axd?site=Default%20Web%20Site',userName='domainUser',password='password',authtype='Basic',includeAcls='False' -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -setParamFile:"Parameters.xml"  -whatif  -allowUntrusted:true

參考

Configuring a Web Server for Web Deploy Publishing (Web Deploy Handler)

JSON 未被定義

客戶抱怨出現了下面的 javascript 錯誤。

JSON 未被定義

原因

IE 7 以下的IE版本, 執行 jQuery 執行 ajax 時會發生此錯誤。

解法

步驟1:使用 NuGet 加入  json2

image

步驟2: 加上如下的 javascript (我使用的是  ASP.NETMVC)

 

<script type="text/javascript">
    if (typeof (JSON) == 'undefined') { 
      $('head').append($("<script type='text/javascript' src='@Url.Content("~/Scripts/json2.js")'>"));
    }
  </script>

2012年5月23日 星期三

Visual Studio 2010 中,MSTest 執行測試時,AppDomain.CurrentDomain.BaseDirectory 的值會隨測試設定不同而改變

今天在寫單元測試時,發現了長久來覺得怪界的現象。這次一定要解開這個謎團

問題:AppDomain.CurrentDomain.BaseDirectory 的值會不同

步驟1:

建立一個測試專案,並在測試中加上

Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
結果是
image
當程式需要讀取同目錄的檔案,例如 xml 檔案時,這是合理的。但在 MSTest 中,檔案會複製到 TestResults\xxxxx\Out 目錄下,(xxxxx 是與時間相關的目錄名稱)
步驟2:
將測試設定的選項Deployment 勾選
image
image
再執行測試一次。結果與步驟1相同。

步驟3:

關掉 Visual Studio 2010後再執行 Visual Studio 2010,重新執行該測試。竟然結果不一樣了!!

image

結論

雖然想寫單元測試,但這個結果未免也太不單元了。與環境相關,算不算是整合測試呢?

2012年5月11日 星期五

如何在 Entity Framework 4.3.1 上使用 enum

使用 Entity Framework 來存取資料實在是很方便,但如果要用 enum 時就不能 work  了。

Entity Framework 5.0 支援 Enum

在尚未上市的 VS11 中,就直接支援了 enum。當然需要用  NuGet 安裝  Entity Framework

image

public class AuditLog
  {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    [Required]
    public string Account { get; set; }
    [Column("AuditTime")]

    public DateTime Date { get; set; }
    [MaxLength(10)]
    public string GroupName { get; set; }

    public int FunctionId { get; set; }

    public AuditStatus Status { get; set; }

    public override string ToString()
    {
      return string.Format("Id={0}, Account={1}, Date={2}, GroupName={3}, FunctionId={4}, Status={5}", Id, Account, Date, GroupName, FunctionId, Status);
    }
  }

  public class BasicContext : System.Data.Entity.DbContext
  {
    public BasicContext(string dbName)
      : base(dbName)
    { }

    public DbSet<AuditLog> AuditLogs { get; set; }
  }

  public enum AuditStatus
  {
    Success,
    Fail
  }

呼叫的方式也非常簡單,就與一般 c# 沒差。

static void Main(string[] args)
    {
      Database.SetInitializer<BasicContext>(new DropCreateDatabaseIfModelChanges<BasicContext>());
      using (var context = new BasicContext("DbName"))
      {
        bool isCreated = context.Database.CreateIfNotExists();
        Console.WriteLine(isCreated);
        var audit = new AuditLog() { Account = "E", Date = DateTime.Now, FunctionId = 1, Status = AuditStatus.Fail };
        context.AuditLogs.Add(audit);
        context.SaveChanges();

        var q = from i in context.AuditLogs
                select i;
        foreach (var auditLog2 in q)
          Console.WriteLine(auditLog2);
      }
    }

產生得資料庫如下圖

image

Entity Framework 4.3.1 的方式

相同的程式,在  4.3.1 版以前是沒有作用的。 Entity Framework 對不支援的欄位,就視而不見,因此相同的程式,在資料庫中就是看不到 Status 的欄位。

有沒有什麼變通方法嗎?有! 只需要改一下屬性存取方式即可。程式如下

public int StatusValue { get; set; }

    public AuditStatus Status
    {
      get { return (AuditStatus)StatusValue; }
      set { StatusValue = (int) value; }
    }

程式寫作時,是透過  Status 來存取,但 Entity Framework 看不懂 AuditStatus 欄位,因此就不理 Status 欄位了。取而代之,是產生 StatusValue 欄位

結果如下

image

 

如果想要產生 Status 欄位呢?再變通一下

[Column("Status")]
    public int StatusValue { get; set; }

    [NotMapped]
    public AuditStatus Status
    {
      get { return (AuditStatus)StatusValue; }
      set { StatusValue = (int) value; }
    }
上述的屬性(Attribute) 告訴 entity framework,Status 這個 enum Property 不必理會。而 StatusValue 這個 int Property 要對應到資料表的 Status 欄位。

2012年5月3日 星期四

IE 的市佔率逐年流失

IE 目前只剩下50%上下而已了。

Chrome 不斷的增加。FireFox 也稍微下降。
這大概與版本更新的速度有關吧。IE 版本更新的速度實在太慢了。

參考 http://www.netmarketshare.com/browser-market-share.aspx?qprid=1 

結論

寫網站的開發人員們,必須測試不同瀏覽器的相容性了。

Share with Facebook