2014年2月15日 星期六

Microsoft Packages版本控管的觀念

在使用Visual Studio來開發程式時,開發者經常透過Nuget來載入一些現成的套件。有經驗的程式師會自已寫Library並封包。但有時候因為懶惰的關係,有時候Lib分類一多時,就會忽略了版本控管的動作,導致於開發時因為Package版本的問題而花許多的時間在找尋奇奇怪怪的錯誤。所以好的開發者,要養成隨時因需求不同結構變更或者工程進度,控管每個方案的大小細項。

-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月14日 星期五

MVC4 - Error 403 Dealing with problems Part1 - 403 - Forbidden: Access is denied.問題處理

開發過Web程式,應該對403這個ErrorCode不陌生,一定會常看到它的敘述如下
「You do not have permission to view this directory or page using the credentials that you supplied.」
它除了「權限限制存取」的意思外,通常另一個最有趣的解讀,就是「讀不到頁面」。

筆者要介紹小問題處理狀況,就是在開發者透過Nuget更新套件時,產生的問題之一處理。
這個問題的產生原因,是在開發者更新System.Web.Mvc這套件時,依賴性的套件如System.Web.Routing,會在更新完之後,重新設定RouteConfig.cs底下RegisterRoutes函數。

但初學者不容易察覺,所以許多人更新完套件後,會有默名的疑問「程式碼沒有更動,但為什麼無法正常的執行?」,其實Nuget已經偷偷的在原始結構上悄稍的改變了Function的陳述結構。因為它的初始它是最原生的結構,並不是專給MVC的架構。所以它的程式碼會長這個樣子:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Routing;
using Microsoft.AspNet.FriendlyUrls;

namespace ManiaControlPanel
{
    public static class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            var settings = new FriendlyUrlSettings();
            settings.AutoRedirectMode = RedirectMode.Permanent;
            routes.EnableFriendlyUrls(settings);
        }
    }
}

這時候我們就要手動去更改它的結構設定,程式碼如下:

using System.Web.Mvc;
using System.Web.Routing;
namespace ManiaControlPanel
{
    public static class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

這樣就可以正常的運作了,這類型的問題是比較不容易察覺,筆者在這分享。

-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月13日 星期四

TFS Deployment to Azure Error的處理: ClientPerfCountersInstaller.exe

Microsoft.WindowsAzure有時候一個處理不小心,會出現下列的錯誤訊息(有些路徑會依版本不同有些許不同:

「Error 161 CloudServices64 : Cannot find file named 'approot\Microsoft.WindowsAzure.Caching\ClientPerfCountersInstaller.exe' for startup task Microsoft.WindowsAzure.Caching\ClientPerfCountersInstaller.exe install  of role ManiaWorkerRole1. C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Windows Azure Tools\2.3\Microsoft.WindowsAzure.targets 985 5 ManiaAppAzure」

這是因為它會載入一個ClientPerfCountersInstaller.exe的執行程式,這時候的處理方式有2種。
一種是到相關文字底上,大部分是存放在ServiceDefinition.csdef裡面。

<Startup priority="-2">
     <Task commandLine="Microsoft.WindowsAzure.Caching\ClientPerfCountersInstaller.exe install" executionContext="elevated" taskType="simple" />

</Startup>

將上面文字上的task標籤整個標註起來如下:

<Startup priority="-2">
     <!--<Task commandLine="Microsoft.WindowsAzure.Caching\ClientPerfCountersInstaller.exe install" executionContext="elevated" taskType="simple" />-->
</Startup>

另一種的方式是將exe文件被標記為CopyAlways,讓程式在編譯時能複製到\ bin目錄。操作方式就是在Microsoft.WindowsAzure.Caching下方ClientPerfCountersInstaller.exe選項按右鍵點擊Properties,然後選擇「Copy to Output Directo CopyAlways」。如同下面圖示範例:


-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月12日 星期三

關於System.Web.Http

有些人會常透過Nuget Manager Console下指令來更新一些套件,新增刪減的過程中,有時候會不知道為什麼會出現一些錯誤,有的錯誤還可以透過訊息排除,但是因為物件導向的特性,有些套件出現的錯誤是無法立即判別原因,筆者要介紹的小部分之一,就是System.Web.Http。
它其實套件,就是Microsoft.AspNet.WebApi,所以只要輸入下列的指令


Install-Package Microsoft.AspNet.WebApi
然後在packages.config底下新增下列文字,依版本的不同,需要查詢新增的版本號然後填上。

<configuration>
  <runtime>
    <assemblyBinding>
      <dependentAssembly>

        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />

        <bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="5.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月11日 星期二

VDPROJ檔案Visual Studio 2012不支援 - 使用InstallShield Limited Edition

VDPROJ檔案是主要與Visual Studio .NET Setup and Deployment Project (Microsoft Corporation)相關的佈暑安裝環境的檔案。不過在Visual Studio 2012版本就不能打開此項目,因為它不支持該項目類型。建議使用Visual Studio的InstallShield Limited Edition(ISLE),直接支持大多數的Windows平台和應用程序運行一個免費的部署解決方案。還可以使用ISLE導入從Visual Studio安裝項目的數據和設置。



末安裝時會跳到提示頁面


文字中有一個下載的超連結,點選進去會進入一個資料填寫的頁面


填寫完之後,會跳至一個已完成填寫的頁面,並會得到一組序號


再重回建立專案的InstallShield Limited Edition上開新的專案,就會跳出輸入序號的視窗


然後把在頁面上取得的序號輸入,就完成了


下面就是InstallShield Limited Edition的操作介面

2014年2月10日 星期一

Windows & Windows 8 Wifi設定命令

Windows 8.1系統中,只要連接過一次Wifi,系統就會自動保留Wifi的資訊。那麼如何才能刪除不需要的連接記錄呢?
Win7系統中一般都是使用"忘記網路"功能,但是由於在Win8.1系統中並沒有像Win7一樣直觀的介面顯示,所以只能通過命令來"忘記網路"。下面介紹一下刪除Wifi連接記錄的具體操作步驟。

 刪除wifi連接記錄
  1. 按鍵盤上的Windows圖型符號鍵+x,運行命令提示字元(管理員),輸入netsh wlan show profile即可看到所有已保存網路的名稱。
  2. 輸入「netsh wlan delete profile name="網路名稱"」
單獨顯示資訊
輸入「netsh wlan show profile name="網路名稱" key=clear」

另一種輸入的指令是清除裡面的設定

輸入「netsh wlan delete profile name="網路名稱" key=clear」


-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月8日 星期六

ASP.Net 無效的回傳或回呼引數

在開發ASP.Net Web時,會遇一個錯誤訊息是:「無效的回傳或回呼引數。已在組態中使用 <pages enableEventValidation="true"/> 或在網頁中使用 <%@ Page EnableEventValidation="true" %> 啟用事件驗證。基於安全性理由,這項功能驗證回傳或回呼引數是來自原本呈現它們的伺服器控制項。如果資料為有效並且是必需的,請使用 ClientScriptManager.RegisterForEventValidation 方法註冊回傳或回呼資料,以進行驗證。」

這樣的問題是在程式中使用了 GridView,
每次執行 Page_Load 事件時都會 Bind 資料到這個 GridView,
遇到 PostBack 時就會觸發上述的錯誤。

解決這個錯誤訊息的辦法是,在 Page_Load 事件中使用PostBack檢查是否為ture,
若否,才將資料綁到 GridView 上頭。例如以下這樣:

protected void Page_Load(object sender, EventArgs e)
{
    // 取得 GridView 內容
    if (!IsPostBack)
    {
        data_bind();    // 自訂的 GridView databind函式
    }
}

或者是只要在.aspx 網頁第一句最後面加上 EnableEventValidation="false" 就行了。

< %@ Page Language="C#" AutoEventWireup="true" CodeFile="Page.aspx.cs" Inherits="Page" EnableEventValidation="false"%>


-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月7日 星期五

C# - Reflection反射運用 Part 2 載入dll實作


Reflection反射運用在很多的技巧上,這次筆者要介紹的,是將已經編譯過的dll檔,透過Reflection來使用裡面的類別。

下面建立一個 ReflectionExample 專案:

public abstract class ReflClassBase
{
    public abstract int add(int v1, int v2);
}

public class ReflClass : ReflClassBase
{
    public ReflClass() { }
    public override int add(int v1, int v2)
    {
        return v1 + v2;
    }

}

將上面的程式編譯過後,會產生一個ReflectionExample.dll的副檔名,新建一個Windows Form應用程式的專案後,將這個dll載入專案裡。

namespace WindowsFormsApplication
{
    public partial class Form1 : Form1
    {
        public Form1()
        {

            InitializeComponent();

            Assembly oa = Assembly.Load("ReflectionExample");

            Type t = oa.GetType("ReflectionExample.TClass");

            TClassBase tcb = (TClass)Activator.CreateInstance(MyType);

            MessageBox.Show(tcb.add(1, 2).ToString());

        }
    }
}


上面的程式結果,就會執行顯示1+2的結果。這種設計概念,是可用運用在編寫好的類別,如視窗,透過反射而可以產生不同的視窗介面。



-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月5日 星期三

C# - WebForm開發一點訣,處理RadioButton單選時的應變處理

其實筆者對於WebForm的開發經驗沒有像用MVC這麼的多,因為一開始的接觸時,筆者就已經開始玩起MVC這樣的開發模式了。不過也是因為工作,有接觸到WebForm這樣的架構。一般初學者對於WebForm的許多類別的運用,常常會摸不著頭緒,尤其是表單這一個部分。本文要介紹的是RadioButton這個物件。它其實就是表單上單選項的Radio,不過很多人會遇到一個問題,有時候不知道要怎麼去改變name的名稱,或者是id名稱。就讓筆者來好好的一一講解。

RadioButton產生出來的ID,是經過運算產生的,如果是要改變ID名稱,第一個方法是透過RadioButton裡的ClientIDMode。
例如下面的例子:

<asp:GridView ID="radioList" runat="server" AutoGenerateColumns="False" Width="100%" CssClass="my_table" BorderStyle="None" BorderWidth="0" GridLines="None" OnRowDataBound=" radioList_RowDataBound">
    <Columns>
        <asp:TemplateField>
            <HeaderStyle CssClass="title_td" />
            <AlternatingRowStyle CssClass="bg" />
            <asp:RadioButton ClientIDMode="Static" name="rbItem" ID="rbItem" runat="server" GroupName="Items" CssClass="rd"/>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

在上面asp:RadioButton標籤之中,會看到一個ClientIDMode,ClientIDMode有四種設定字串,它分別的意思:


  • AutoID - ClientID 值是透過串連每個父命名容器的 ID 值與控制項的 ID 值產生。 在呈現控制項之多個執行個體的資料繫結情節中,遞增值會插入控制項之 ID 值的前面。 各區段是以底線字元 (_) 分隔。 這是在比 ASP.NET 4 還舊版本中唯一可以使用的演算法。
  • Inherit - 該控制項可以繼承ClientIDMode設定其NamingContainer控制項。
  • Predictable - 這個演算法用於資料繫結控制項中的控制項。 ClientID 值是透過串連父命名容器的 ClientID 值與控制項的 ID 值產生。 如果控制項是資料繫結控制項,並且會產生多個資料列,則 ClientIDRowSuffix 屬性中指定之資料欄位的值會加入結尾處。 針對 GridView 控制項,可以指定多個資料欄位。 如果 ClientIDRowSuffix 是空屬性,則會在結尾處加入序號,而不是資料欄位值。 各區段是以底線字元 (_) 分隔。
  • Static - ClientID 值設定為 ID 屬性的值。 如果控制項是命名容器,則對於其包含的所有控制項而言,會用來做為命名容器之階層架構的最上層。

當ClientIDMode的字串設定為"Static"時,就可以在cs底下的物件ID更改名稱。

protected void radioList_RowDataBound(object sender, GridViewRowEventArgs e)
{
    var rbItem = e.Row.FindControl("rbItem"as RadioButton;
    rbItem.ID = "rdItem";
}

另一個方法,是jQuery可以將頁面上任何的radio裡有類似以Items為組合字的每個radio都跑過一遍,所以我們可以透過下面的方式,把所有的id都統一。
<script type="text/javascript">
$("input[name$='Items']:radio").each(function () {
    $(this).attr("id""rdItem");
});
</script>

所以結果就會是如下面執行前跟執行後的變化:

-執行前-
<span class="rd"><input id="C_C_gvPreAppList_rbItem_0" type="radio" name="ctl00$ctl00$C$C$ radioList$ctl02$Items" value="rdItem" /></span>

-執行後-
<span class="rd"><input id="rbItem" type="radio" name="ctl00$ctl00$C$C$ radioList$ctl02$Items" value="rdItem" /></span>

改Input底下Name的名稱,通常還是只能靠JavaScript或jQuery。同樣的,RadioButton產生出來的Name,是經過運算產生的,所以產生出來的值都不一樣,這樣在Form底下是無法有單一控制這樣的效果,所以要經過一道程序來統一名稱,下面的方法,跟更改ID很雷同,只是字串要改成"id"。

<script type="text/javascript">
 $("input[name$='Items']:radio").each(function () {
    $(this).attr("name""rbItem");
});
</script>

-執行前-
<span class="rd"><input id="rbItem" type="radio" name="ctl00$ctl00$C$C$ radioList$ctl02$Items" value="rdItem" /></span>

-執行後-
<span class="rd"><input id="rbItem" type="radio" name="rdItem" value="rdItem" /></span>

有一點要注意的事,jQuery新舊版有方法上執行的差異,舊版的採用attr,新版採用prop,需要到官網查詢使用的版本來對照,如下例子:

舊版:
$(this).attr("id""rdItem");
$(this).attr("name""rdItem");

新版:
$(this).prop("id""rdItem");
$(this).prop("name""rdItem");


要將所有的radio監聽每個點下去觸發事件的程式寫法如下:
<script type="text/javascript">
$('input[type=radio]').bind('click'function () {
    alert("選擇radio的name" + $(this).attr('name'));
}
</script>

下面這方法也是會對每一個radio都監聽,但是比較適用在已經checked時候,要做的判斷,字串中的Items就是每一個name上面有相似的Items都會觸發,例如頁上面同時有radioList$ctl01$Items、radioList$ctl02$Items的時候:
<script type="text/javascript">
var radioName = "";
$("input:radio[name$='Items']").click(function () {
    radioName = $("input:radio[name$='Items']:checked").attr("name");
}
</script>


-雲遊山水為知已逍遙一生而忘齡- 電腦神手

2014年2月4日 星期二

C# - Windows form 的 DataGridView

在微軟 .NET 的架構中,MenuGridView是一個強大但複雜的元件,其實大部分時候不會將這個元件與資料庫綁在一起,但是微軟函式庫如此的廣大,難道沒有一個可以更方便的方法嗎?
答案是有的,那就是運用DataGridView這簡單的元件。

用 Visual Studio 拉出一個 DataGridView 物件後,名稱為 dgViewMenu,可以點選其屬性中的 Columns 欄位,然後用視覺化的方式加入兩個 Column,並設定好名稱為 name和price。

接著可以用程式填入資料到 rows 屬性中,就完成了整個表格建立的工作,如此就不需要將 DataGridView 與資料庫綁在一起,也能有效的利用 DataGridView 元件了。

namespace MenuGridView
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            DataGridViewRowCollection rows = dataGridViewMenu.Rows;
            rows.Add(new Object[] { "紅茶"25 });
            rows.Add(new Object[] { "綠茶"25 });
        }
    }
}

-雲遊山水為知已逍遙一生而忘齡- 電腦神手