2017年8月5日 星期六

【MVC】在IIS7.5中設定環境給MVC用

只是將ASP.NET WebForm發布到IIS時還挺順利的
我只有在設定讓區網內的其他電腦可以連到虛擬機中的IIS卡過,而且這問題主因在不熟VMWare,而不是IIS
但MVC光是這IIS這邊就麻煩不少了

測試環境: win7 pro & IIS 7.5
測試網站: 微軟提供的教學範本



前面的起手式與傳統網站相同,都是要開啟Windows功能 (IIS因為安全性關係,預設關閉)


1. 開啟「控制台」找到「開啟或關閉Windows 功能」,參考下圖將功能開啟
  • Web 管理工具 -> IIS管理主控台 (非必要,但強烈建議裝)
  • www服務 -> 應用程式開發功能 -> ASP.NET (必要)
  • www服務 -> 應用程式開發功能 -> ISAPI 篩選器 (必要)
  • www服務 -> 應用程式開發功能 -> ISAPI 擴充程式 (必要)



2. (不見得需要做)如果IIS比.NET Framework後裝,就要接著開啟cmd執行註冊(依OS選擇註冊方式),讓他跑一下(數秒而已)

  • OS為32bit「C:/Windows/Microsoft.NET/Framework/v4.0.30319/aspnet_regiis.exe -i」
  • OS為64bit「C:/Windows/Microsoft.NET/Framework64/v4.0.30319/aspnet_regiis.exe -i」
(大部分的開發環境可能都是後裝,除非一開始就確定要當AP Server)

3. 然後就能在「開始」輸入「IIS」把主控台叫出來
 



如果是WebForm,到這裡就可以開始Publish網頁跟指定路徑了,但是佈署mvc比普通網站更麻煩,所以從這裡開始要多設定一些!

4. 開啟「ISAPI及CGI限制」的功能視窗
 


4.1 然後將「限制」改為「允許」 (最低限度是啟動第三列的64bit就能執行了。)
 


5. 然後就可以Publish專案啦,方法可以參考這影片,這裡不細說。畢竟都要設定IIS了,應該... 不會不知道怎麼publish基本款的網站吧?
https://www.youtube.com/watch?v=FzwcD_XQ4ko


6. 回到IIS主控台,對「站台」右鍵 -> 點「新增網站」 然後參考下面設定

圖片太小的話,可以開新分頁去看
※應用程式集區就是「步驟4.1中『允許』的那個程式集區

※我偏好使用不同的連接port去設定網站,這樣就不用記一堆IP,但是注意要那條port有沒有被防火牆鎖起來就是了
 

7. 如果是VS預設的MVC範本,到此就可以執行了
用「瀏覽」或者直接在瀏覽器輸入網址



參考來源:iis部署asp.net mvc網站出錯的解決方法 




如果網站有使用到編譯為32bit的DLL,就還要多設定一小段

Extra 1. 看是哪個站台有需要用到32bit的DLL,對它指定的「應用程式集區」右鍵→點「進階設定



Extra 2. 將「啟用32位元應用程式」設定為True就可以了。
當然也能為了它新增個別的程式集區,但是這步一定要做!


Extra 3. 保險起見,將網站停止後,再啟動吧。

參考來源:在Windows7 x64的IIS使用32bit的odbc driver 

2017年7月30日 星期日

【WPF】執行背景工作時,讓畫面不會看起來像卡住


只是想在WPF中使用熟悉的Process Bar,那就別花時間看這篇了
到 youtube去搜尋比較快

這篇不會提到Process Bar,雖然同樣的原理也能用在Process Bar,甚至是自訂的任何進度條。這篇還順便迴避某些書中範例無法回傳string的問題。

原因是WPF畫面的呈現和背景工作是分開的
當程式在忙碌時,畫面會乖乖的一直等背景工作跟他說OK才刷新
(圖片看起來會動,就是因為畫面不斷的刷新喔!)

想像影片前半段,希望能夠「圖片會動、文字會逐項目顯示」,那就需要用到
Async 和 Await
來寫出非同步程式,這樣畫面就不會等到海枯石爛了!
沒聽過「非同步, await, async」的也不用擔心,可以先理解差異,有興趣再找資料吧

●先來一段失敗的程式碼

        private void test_Click(object sender, RoutedEventArgs e)
        {
            //沒使用async & await
            showLog.Text = "轉檔開始(2秒/個)\r\n";
            for (int i = 0; i < 3; i++)
            {
                showLog.Text += "開始第" + (int)(i + 1) + "個轉檔...";
                Thread.Sleep(2000); //模擬轉檔時會停頓的時間
                showLog.Text += "End\r\n";
            }
            showLog.Text += "轉檔全部結束\r\n";
        }
●然後這是成功的程式碼

        private async void test_Click(object sender, RoutedEventArgs e)
        {
            //使用async & await
            showLog.Text = "轉檔開始(2秒/個)\r\n";
            for (int i = 0; i < 3; i++)
            {
                showLog.Text += "開始第" + (int)(i + 1) + "個轉檔...";
                showLog.Text += await ConvertFile("End\r\n");
            }
            showLog.Text += "轉檔全部結束\r\n";
        }

        public Task<string> ConvertFile(string str)
        {
            return Task.Factory.StartNew(() => this._ConvertFile(str));
        }

        public string _ConvertFile(string para1) {
            Thread.Sleep(2000); //模擬轉檔時會停頓的時間
            return para1;
        }

知道怎麼套用await和async,讓畫面不會卡住了嗎?
還是不懂的話,再繼續往下看吧


1. 在可能會執行到需要花時間,但前後想加上其他程式碼的方法(method)的宣告加上「async」,這樣之後要加的await才有作用。只加async卻沒加await,也不會有作用的喔!
before:
private void test_Click(object sender, RoutedEventArgs e){...}
after:
private async void test_Click(object sender, RoutedEventArgs e){...}
2. 宣告一個回傳「數值或字串」的方法 (※不見得要寫成能傳參數,只寫"public string _ConverFile()"也行) 
before:
private async void test_Click(object sender, RoutedEventArgs e){
        ...
        Thread.Sleep(2000); //模擬轉檔時會停頓的時間
        ...
}
after:
private async void test_Click(object sender, RoutedEventArgs e){
        ...
        //Thread.Sleep(2000); //將要背景執行的function搬出這個method
        ...
}
public string _ConvertFile(string para1) {
    Thread.Sleep(2000); //模擬轉檔時會停頓的時間
    return para1;
}
3. 再宣告一個Task,要利用它awaitable的特性,同時利用方便的「Factory.StartNew(...)」來快速的建立與啟動新Task (※也可以不丟參數,直接寫成 "public Task ConverFile()")  
public Task ConvertFile(string str)
{
    return Task.Factory.StartNew(() => "action");
}
4. 將「步驟2」跟「步驟3」結合
public Task ConvertFile(string str)
{
    return Task.Factory.StartNew(() => this._ConvertFile(str+"只是個丟參數的地方")); 
}

5. 將組好的task放在method中使用,記得要加上「await
private async void test_Click(object sender, RoutedEventArgs e){
        ...
        showLog.Text += await ConvertFile("End\r\n"); //取代原本會拖時間的function
        ...
}

然後就...完成! 可以執行程式,體驗差異了!

【延伸】
有興趣的可以試試看:
1. 只加Async,卻沒用Await,是不是也能成功?
2. 只是把工作丟給Task,卻沒有用Async和Await,是不是也能成功?

如果好奇「await和async」的原理,可以看MSDN的介紹
使用Async 和 Await 設計非同步程式 (C# 和 Visual Basic)
然後找到段落「非同步方法中執行了哪些工作」,會有詳細的執行流程
圖看一次不懂沒關係,不需要刻意去記住,用多就會理解了

2017年3月10日 星期五

【C#】跨視窗傳遞集合

我預計的期望是:
  在「視窗A」點按鈕(Button) → 彈出「視窗B」→ 將「視窗B」更改後的數值回傳

由於「視窗B」的設定不是只有一項,要回傳的話一定是陣列(Array)或集合(Collections)
好處是彼此的變數並不直接干涉,不用因為改了變數名,另一個也要跟著改。

※我用的是WPF,會跟WinForm有一點差距,但是概念差不多。偏基礎的部分,下面介紹就省略了,畢竟需要跨視窗還很在意修飾詞(public, private...)的人,看廢話也覺得煩吧。


視窗A - MainWindow
        private Dictionary<stringstring> SetDic = new Dictionary<stringstring>();
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            SettingWindow sw = new SettingWindow(SetDic);
            if (sw.ShowDialog() == true//從設定中取值
                SetDic=sw.ApplySetting();
         }

視窗A的程式碼主要是
第一列:建立Dictionary的集合「SetDic」,作為接收與後續利用
第四列:在事件中用實做視窗B「SettingWindow」,視窗B的建構式看下面
第五、六列:如果在視窗B有點「確定」之類的,那就會執行「SettingWindow」中寫好的方法,將回傳的集合賦值給「SetDic」

視窗B - SettingWindow
    public partial class SettingWindow
    {
        private Dictionary<stringstring> _SetDic;
        public SettingWindow(Dictionary<stringstring> _SetDic)
        {
            //(不重要,中略)
            _SetDic=SetDic;
        }
        private void Apply_Click(object sender, RoutedEventArgs e)
        {
            //(不重要,中略)
            this.DialogResult = true;
            this.Close();
        }
        internal Dictionary<stringstring> ApplySetting() {
            //(不重要,中略)
            return _SetDic;
        }
    }

視窗B就是重頭戲了,分成
第一列:可以看到這個視窗的類別名稱是「SettingWIndow」
第三列:建立一個用來暫存從視窗A丟過來的集合「_SetDic」
第四~八列:由於要接視窗A丟過來的「SetDic」,所以在寫建構式時,要定義參數型別。然後在將接到「SetDic」賦予給「_SetDic」
第九~十四列:這個是點「確定」時,會觸發的事件。重點在第十三列與第十四列的「this.DialogResult = true; this.Close();」,功能分別是「要讓視窗A第五列的IF判斷能成功觸發、關閉視窗B」
第十五~十八列:寫一個會回傳數值的方法,把在視窗B變更過的「_SetDic」回頭賦予給「SetDic」


2016年6月29日 星期三

[WPF]使用App.config來集中管理連線字串(ConnectionString)

因為內部的程式(VB6, winForm)要整個翻新,所以從ASP.net被拉回寫視窗程式
想說既然都要翻新,那乾脆整個框架一起翻新就用了M$支援度比較高的WPF
當然也不意外地要跟資料庫溝通,也就整個從Access換去SQL server

---------好,上面都不是重點, 只是緣由-----------------------------------

既然要跟資料庫結合,一定少不了「連線字串」
因為我都是ADO.net去寫,對於連線字串的依賴相當大
至於每次都要重寫但不易管理的方法就不提了,書本上都有
我這邊是寫個人偏好的集中管理 :D

1. 加入參考「System.Configuration.dll」
2. 在App.config中的<configuration>...</configuration>中加上

<connectionStrings>    
    <add name="DBconnStr" connectionString="要使用連線字串" />
</connectionStrings>

3. 在要設定連線字串的地方用以下進行代入
C#
string connStr = ConfigurationManager.ConnectionStrings["DBconnStr"].ConnectionString;
VB

Dim connStr As Stringction(Configuration.ConnfigurationManager.ConnectionStrings("DBconnStr").ConnectionString

----------------------------
如果直接 new SqlConnection, 可參考下列寫法

SqlConnection connstr = new SqlConnection(ConfigurationManager.ConnectionStrings["AL_connstr"].ConnectionString)

2016年5月17日 星期二

[LINQ]在LINQPad中使用LinqToExcel(如何引入參考與Namespaces)

LINQPad是一個可以快速檢視LINQ查詢結果的工具(而且是麻雀雖小但五臟俱全)
不像在VS中還需要特別寫顯示的畫面,對於Demo來說相當方便
這篇文章只是從零到在LINQPad使用LinqToExcel的教學文
重點在於「如何引入參考和命名空間」
LINQPad的詳細使用可以找google小姐

LinqToExcel對針對只「讀」的資料而言,比NPOIOpenXML更佳的選擇

LINQPad版本(官網下載的FREE)v4.50.00
LinqToExcel版本(NuGet抓取)v1.10.1 

Step1: 取得LINQPad


不喜歡安裝的,可以點紅框處。至於選LINQPad 5 還是LINQPad 4 則取決於用的.NET Framework版本

下載後,解壓縮在尬意的位置就可以了,然後點「LINQPad.exe」執行
打開LINQPad後,畫面長這個樣子

Step2: LINQPad環境設定

要使用LinqToExcel前,需要將DLLLINQPad認識。(加入參考與命名空間)
點工具列的「Query」→「Query Peoperties
在「Additional Reference」的頁籤中,利用「Browse...」將已經抓好的LinqToExcel相關DLL如圖所需添加(Name欄位才有參考價值)

再換到「Additional Namespace Imports」頁籤中添加命名空間
如果不知道要打什麼或是擔心打錯的,點「Pick from assemblies
右側就會自動產生相應的命名空間,需要的再點「< Add Selected Namespaces」添加
最後,當然就是點OK

Step 3:Query

Language切換到「C# Program 」後 (Language詳細請參閱:LINQPad: The Ultimate .NET Scratchpad)
在輸入區打上下方語法後,Excute(F5)
----------------------------------------------------------------------------------------
void Main()
{
    var fileName=System.IO.Path.Combine(@"E:\備份\2016年度","SOP文件總攬.xlsx");
    var excelFile=new ExcelQueryFactory(fileName);
   
    var excel=excelFile.Worksheet(1); //亦可輸入工作表名 excelFile.Worksheet(“工作表1”)
    foreach (var element in excel)
    {
        element.Dump();
        "".Dump();
    }
}
----------------------------------------------------------------------------------------

然後你就得到它了

2016年2月22日 星期一

[豆知識]在網頁中貼上有上色的VS相關語法

沒技術量的筆記

以往在網頁或Blog中要貼語法又要有顏色時,不外乎這幾種選擇

  • 再自己手動上色
  • 使用網路上的語法上色器
  • 用js進行上色
  • 貼圖(需大量解說的才用方法, 畢竟處理相對耗時)


最近發現一個更簡單, 非常適合懶人的方法

  1. 將在VS中複製的語法,貼上Word
  2. 然後再從Word中複製,轉貼到網頁或Blog


當然這作法去看html原始碼時,某些有強迫症或潔癖的人會吐血(我有一點)
把很多不必要的Code都包進來了
不過當我文章大致完稿,不再去弄排版只差程式碼上色時
就會這樣使用

如果各位有更好的點子,也請多多指教了。

2016年1月29日 星期五

[CSS]利用CSS3與JQuery達成開合面板特效

測試的chrome版本: 48.0.2564.97
其他版本或瀏覽器, 可能會有呈現上的差異, 請適當的修改各處的CSS

目的:用一張圖靜態的圖搞定特效

1.滑鼠移入時三角形變亮 
2.點擊時, 旋轉三角形與展開區域









下面是原料的原始碼

CSS
    <style type="text/css">
        /*補間動畫*/
        @keyframes arrow {
        0%   { transform:rotate(0deg);}   /*初始的呈現*/
        100% { transform:rotate(90deg); -webkit-filter: brightness(200%);} /*最終的呈現*/
        }
        @keyframes arrow_close {
        0%   { transform:rotate(90deg);}
        100% { transform: rotate(0deg); -webkit-filter: brightness(100%);}
        }

        /*圖片套用的樣式*/
        .test-arrow {
            animation-name: arrow; /*使用的補間動畫*/
            animation-duration: 0.5s; /*動畫時間長度*/
            transform:rotate(90deg); /*相對於原圖的旋轉角度*/
            -webkit-filter: brightness(200%); /*相對於原圖的亮度*/
        }

        .test-arrow-close {
            animation-name: arrow_close;
            animation-duration: 0.5s;
            transform:rotate(0deg);
            -webkit-filter: brightness(100%); /**/
        }
    </style>

●混雜著asp.nethtml(編譯到網頁時, 還是會回到html)
         <table class="fastFunc" style="width: 90%;">
           <tr style="background-color: #7292CC; color: #FFFFFF;">
                <td>
                    <img id="i_arrow" class="i_toggle" src="../BlueTriangle_glow.png" />快速停用
                </td>
           </tr>
           <tr>
<td>
               <asp:Panel id="arrow" CssClass="p_toggle" runat="server" BackColor="#C6DAF8">
                  //(自由發揮)
</asp:Panel>
               </td>
</tr>
        </table>


 重這邊開始有區別, 這裡是jQuery與js主要運作的地方

第一種, 較直觀的方法(直接指定ID)

優:簡單不容易指錯, 在測試和規劃初期可以減少需排除的錯誤, 相當適合只用一次的功能
缺:想重複使用功能時, 會需要寫進所需的code, 讓檔案大幅成長

    <script type="text/javascript">
        $(document).ready(function () {
            $("#arrow").hide();
            $("#i_arrow").mouseover(function () { $(this).css("-webkit-filter", "brightness(200%)") })
            $("#i_arrow").mouseout(function () { $(this).css("-webkit-filter", "brightness(100%)") })

            $("#i_arrow").click(function () {
                $(".fastFunc").slideToggle(300);
                if (this.className == "test-arrow") {
                    this.className = "test-arrow-close";
                }
                else
                    this.className = "test-arrow";
            });
        });
    </script>


第二種, 較抽象的方阿 (利用this與遍歷)

優:只需寫一次, 並透過適當的條件選擇, 就能套用在不同區塊
缺:不熟悉selector或架構尚未定型的開發中頁面, 使用此方法反而會增加困擾

    <script type="text/javascript">
        $(document).ready(function () {
            $(".p_toggle").hide();
            $(".fastFunc .i_toggle").mouseover(function () { $(this).css("-webkit-filter", "brightness(150%)") })
            $(".fastFunc .i_toggle ").mouseout(function () { $(this).css("-webkit-filter", "brightness(100%)") })

            $(".fastFunc .i_toggle").click(function () {
                $(this).parents("tr").next().find(".p_toggle").slideToggle(300);
                if (this.className == "test-arrow")
                    this.className = "test-arrow-close";
                else
                    this.className = "test-arrow";
            })
        });
    </script>

可以注意看其實程式碼差不多而是差別在selector的寫法