2013年9月16日 星期一

[yeoman]grunt test : cannot start chrome

在windows 中使用 yeoman 中的 grunt test,會發生找不到預設的 chrome 的問題,可透過修改路徑解決。
yoeman_grunt_test_error
首先,開啟 ./node_modules/karma-chrome-launcher/index.js
接著修改其路徑為chrome安裝之路徑,如下圖(chrome預設路徑)
CHROME_BIN
重新執行 grunt test,搞定!!~^^

2013年7月8日 星期一

[MS-SQL]安裝時發生錯誤『檢查現有的效能計數器登錄區是否一致』

這是上星期五幫客戶安裝 HP 伺服器後,要安裝SQL時發生的錯誤,因為來不及卡圖! 所以這邊就做個簡易分享,除了做個紀錄之外也希望若網友有遇到類似問題的話,可以少走一點冤枉路嚕。

 

當您使用HP 官方的 SmartStart 安裝伺服器OS之後,要安裝SQL 時就會發生這一錯誤,原因是因為HP的 SmartStart 一開始並沒有繁體中文選項可選,因此預設會將"地區及語言→系統管理→非Unicode程式的語言,設定為英文"!!

而預設的英文語系在登錄檔中的『效能計數器登錄區』是在 009 這個目錄中,而當你裝好繁中OS之後,卻是要走0404 目錄,因此就會造成這個結果。

英文語系 :

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009]

 

繁中語系:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\0404]

 

解法有三種!!!

1.不要透過 HP 的 SmartStart 去安裝OS,直接從OS的安裝片去安裝!! 

OS: 很麻煩阿,還要重裝,真是浪費生命,而且其他相對應的驅動、磁碟陣列卡還要另外裝!!超麻煩,有沒更好解法呢?請看第二種方式!! 嘿嘿....

 

2.控制台→地區及時間→系統管理,修改"非Unicode程式的語言"為繁體中文。然後重開機,系統就會將效能計數器資訊寫入0404 ,再安裝SQL2008~~搞定!!

OS:還要重開機很麻煩...........我是懶人有沒有更好方法? 有的....

 

3.將 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\CurrentLanguage] 匯出,

再使用記事本開啟修改路徑為0404,接著再對這修改過的登錄檔按兩下註冊,接著就能快樂繼續安裝 SQL 2008 嚕。

 

CurrentLanguage

0404

 

打完收工,希望有朝一日,這篇能幫助到其他一樣被HP Server 困擾的IT人員。

2013年6月9日 星期日

[Asp.net MVC] Custom Action Filter and Trace

上一篇,已經針對 Action Filter 作了一個初步的介紹,這篇就來試著實作自己的Action Filter。

Action Filter 是實作 一個繼承 ActionFilterAttribute 的一個 Attribute 類別, ActionFilterAttribute 是一個抽象類別,包含四個 virtual methods : OnActionExecuting、OnActionExecuted、OnResultExecuting、OnResultExecuted。

這邊是MSDN的原文說明,相信會讓大家有更清楚的認知:

An action filter is implemented as an attribute class that inherits from ActionFilterAttribute. ActionFilterAttribute is an abstract class that has four virtual methods that you can override: OnActionExecuting, OnActionExecuted, OnResultExecuting, and OnResultExecuted. To implement an action filter, you must override at least one of these methods.

The ASP.NET MVC framework will call the OnActionExecuting method of your action filter before it calls any action method that is marked with your action filter attribute. Similarly, the framework will call the OnActionExecuted method after the action method has finished.

The OnResultExecuting method is called just before the ActionResult instance that is returned by your action is invoked. The OnResultExecuted method is called just after the result is executed. These methods are useful for performing actions such as logging, output caching, and so forth.

 

首先我們先建立一個 MVC 專案,並新增一個Filter資料夾,然後在其中新增一個繼承 ActionFilterAttribute 的 Trace class ,並 override ActionFilterAttribute 的四個 virtual methods :

    public class Trace : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Debug.WriteLine("OnActionExecuting");
base.OnActionExecuting(filterContext);
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Debug.WriteLine("OnActionExecuted");
base.OnActionExecuted(filterContext);
}

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Debug.WriteLine("OnResultExecuting");
base.OnResultExecuting(filterContext);
}

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Debug.WriteLine("OnResultExecuted");
base.OnResultExecuted(filterContext);
}
}

 


接著,按下F5讓它動起來,觀察執行的先後順序是否如同上面所描述的一樣  :


sdsd


 


那如果 Action Filter 套用多個呢?  首先我們再新增一個 ActionFilter (Log) :

    public class Trace : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Debug.WriteLine("OnActionExecuting from Trace");
base.OnActionExecuting(filterContext);
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Debug.WriteLine("OnActionExecuted from Trace");
base.OnActionExecuted(filterContext);
}

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Debug.WriteLine("OnResultExecuting from Trace");
base.OnResultExecuting(filterContext);
}

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Debug.WriteLine("OnResultExecuted from Trace");
base.OnResultExecuted(filterContext);
}
}

public class Log : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Debug.WriteLine("OnActionExecuting from Log");
base.OnActionExecuting(filterContext);
}

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Debug.WriteLine("OnActionExecuted from Log");
base.OnActionExecuted(filterContext);
}

public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Debug.WriteLine("OnResultExecuting from Log");
base.OnResultExecuting(filterContext);
}

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Debug.WriteLine("OnResultExecuted from Log");
base.OnResultExecuted(filterContext);
}
}

將 Trace、Log 兩個 Filter 都套用到 Action之後,我們會得到以下的結果


sdx


從上面的結果我們可以發現 Action Filter 中的 Executing 是由上而下執行,而 Executed 是由下而上執行,類似堆疊 "後進先出"的概念。


ActionExecuting、ResultExcuting 執行階段是可以被終止、Cancel 的(例如當發生execption時),所以我們再把 Trace 這個 Filter 修改一下,使其拋出一個 non-null Result,來模擬這個狀況

        public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Debug.WriteLine("OnActionExecuting from Trace");
//加入下面這一行,讓result 為 non-null
//也就是 filterContext.RouteData.Values.ContainsValue("Cancel") = true
filterContext.Result = new EmptyResult();
base.OnActionExecuting(filterContext);
}

 


我們會得到以下的結果 :


sss


可以發現,當Trace 的 OnActionExecuting 事件被中止,尚未執行的Log OnActionExecuting 也一樣被中止,直接進入OnResultExecuting 繼續執行,由此可知 OnActionExecuting 和 OnResultExecuting 兩個是獨立的流程,並不會因為 OnActionExecuting 發生Cancel 而影響 OnResultExecuting 。


 


參考資料 :


MSDN -- Filtering in ASP.NET MVC

2013年6月8日 星期六

[MS-SQL] 備份組包含目前現有的XXX資料庫以外的資料庫備份

當我們在還原資料庫時,時常會遇到這個錯誤,這邊就記錄一下完整步驟,避免每次都要重新請教G大神或從已經爆炸的書籤中找解法 Orz....
錯誤畫面 :
未命名

解決方式 :
1.先指向   資料庫---> 系統資料庫 –> master   , 新增sql查詢。
masterDB
2.在sql 查詢視窗 輸入以下指令 :
restore DATABASE xxxx  -- 指定 欲還原的資料庫名稱db  
from disk='D:\DbBack\xxxx.bak'  -- 設定 資料庫備份檔 .bak 路徑
with 
move 'xxxx' to 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\Data\xxxx.mdf',      -- 設定成 MSSQL資料庫存放路徑 (mdf)
move 'xxxx_Log' to 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\Data\xxxx_log.ldf'  -- 設定Log 存放路徑
,NoRecovery
,Replace
go

3.執行完畢,重新整理資料庫畫面,會變成以下畫面 :

正在還原

4.接著再對 (正在還原....) 的這個資料庫點右鍵    工作-->還原

還源

5.加入備份檔 .bak 所在路徑

還原2

6.勾選還原資料庫

勾選還原資料庫



OK!! 很懶惰的一篇分享文.....(用一堆圖片帶過 Orz)  ….. 結束.....The End

2013年6月6日 星期四

[Asp.net MVC] Action Filter


在ASP.net MVC 中有以下幾種預設 filters providers :
過濾器類型 中文名稱 介面 實作
Authorization Filters 授權過濾器 IAuthorizationFilter AuthorizeAttribute
ChildActionOnlyAttribute
RequireHttpsAttribute
ValidateAntiForgeryTokenAttribute
ValidateInputAttribute
Action Filters 動作過濾器 IActionFilter ActionFilterAttribute
OutputCacheAttribute
AsyncTimeoutAttribute
Result Filters 結果過濾器 IResultFilter ActionFilterAttribute
Exception Filters 例外過濾器 IExceptionFilter HandleErrorAttribute
OutputCacheAttribute

執行順序 :
action filter life cycle
                                                       (圖片引用自http://www.dotnetexpertguide.com)


原文說明 :
  • Authorization filter, which makes security decisions about whether to execute an action method, such as performing authentication or validating properties of the request.
  • Action filter, which wraps the action method execution. This filter can perform additional processing, such as providing extra data to the action method, inspecting the return value, or canceling execution of the action method
  • Result filter, which wraps execution of the ActionResult object. This filter can perform additional processing of the result, such as modifying the HTTP response.
  • Exception filter, which executes if there is an unhandled exception thrown somewhere in action method, starting with the authorization filters and ending with the execution of the result. Exception filters can be used for tasks such as logging or displaying an error page.

ASP.NET MVC 目前內建的幾種 Filter :
  • [Authorize] 與Membership or FormsAuthentication 配合使用,驗證使用者是否有被授權執行Action,若驗證失敗會轉向預設登入頁面。
  • [AllowAnonymous] 套用此屬用,將會使此Action不被 Authorize 所作用,可不接受驗證授權即執行Action。
  • [ChildActionOnly] 套用此屬性之後,該Action 將只可透過 Html.RenderAction 執行,不可由外部URL 或是 RedirectToAction 所執行。
  • [RequireHttps] 僅可透過Https安全連線存取,若透過一般Http做存取,將會自動導向Https。
  • [ValidateInput] ASP.NET MVC 預設會將所有透過Form來的輸入資料作驗證,檢查是否有惡意的標籤或是程式碼,因此若要取得使用者所輸入的HTML標籤或是JS,就必須將此屬性設定為False。
  • [ValidateAntiForgeryToken] 在ASP.NET MVC 4 所新增的屬性,用以防止CSRF攻擊,使用時除了必須在Action套用此屬性之外,在View頁面的 Form表單中,必須在Sumbit之前插入 @Html.AntiForgeryTolen( ),否則會引發 『需要的反仿冒 Cookie "__RequestVerificationToken" 不存在 』的錯誤。
  • [AsyncTimeOut] 設定執行非同步控制時的 TimeOut 時間(毫秒),這邊須注意此屬性僅在 Controller 繼承 AsyncController 時,才有作用。
  • [NoAsyncTimeOut] 設定執行非同步控制時,不會有TimeOut時間,會不斷等待直到執行完畢為止,也一樣必須繼承AsyncController時,才有作用。
  • [OutputCache] 套用此屬性,可設定瀏覽器快取的相關設定。
  • [HandleError] 套用此屬性之後,不管是在Action執行階段,或者Result時發生錯誤,皆會觸發HandleError.OnException,若沒特別指定錯誤事件和指定的View,預設會將頁面導向預設的 /View/Shared/Error.cshtml。

Filter 作用域 :
1.僅套用於單一Action
    
    [HandleError]  //加在Action 之上
    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";
        return View();
    }

2.套用整個Controller
    
    [HandleError] //套用整個Controller
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
            return View();
        }
    }

3.註冊為全域(套用整個Asp.net MVC 專案)
    
//在App_Start中的FilterConfig中註冊filter
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }
    }





參考資訊

msdn--Filtering in ASP.NET MVC

asp.net mvc 官網教學 Home/MVC/Tutorials/Chapter 11. Hands On Labs/ASP.NET MVC 4 Custom Action Filters

2013年6月3日 星期一

[Asp.net MVC] FileResult

在ASP.NET MVC 中,若要實現檔案文件等的上下傳,最簡單的就是使用FileResult。

FileResult 是基於檔案文件的一個ActionResult實作,目前在ASP.NET MVC 中定義了如下三個FileResult的實作 :

  • FileContentResult: Sends the contents of a binary file to the response.
protected virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName);
  • FilePathResult: Sends the contents of a file to the response
protected virtual FilePathResult File(string fileName, string contentType, string fileDownloadName);
  • FileStreamResult: Sends binary content to the response by using a Stream instance
protected virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName);

實作範例 

1.FileContentResult

        public FileContentResult fileContextResult(int productId = 2)
        {
            var prod = db.Products.FirstOrDefault(q => q.ProductID == productId);
            return prod != null ? File(prod.ImageData, prod.ImageMimeType) : null;
        }
2.FilePathResult
        public FilePathResult filePathResult()
        {
            ViewBag.Status = "FilePathResult";
            string path = Server.MapPath("/Content/Guns/2.png");
            return File(path, "image/png", "02.png");
        }
3.FileStreamResult
        public FileStreamResult fileStreamResult()
        {
            string path = Server.MapPath("/Content/Guns/2.png");
            var image = new Bitmap(path);            
            MemoryStream  stream = new MemoryStream();
            image.Save(stream, ImageFormat.Jpeg);
            stream.Seek(0, SeekOrigin.Begin);
            return File(stream, "image/jpeg");
        }

View

@ViewBag.Status

@Html.ActionLink("Download", "filePathResult")

上傳實作

Action :
        [HttpPost]
        public ActionResult Edit(Product product, HttpPostedFileBase image)
        {
        // 注意這邊須使用 HttpPostedFileBase 來接 multipart/form-data 格式的資料
            if (ModelState.IsValid)
            {
                if (image != null)
                {
                    product.ImageMimeType = image.ContentType;
                    product.ImageData = new byte[image.ContentLength];
                    image.InputStream.Read(product.ImageData, 0, image.ContentLength);
                }

                db.SaveProduct(product);
                TempData["message"] = string.Format("{0} has been saved", product.Name);
                return RedirectToAction("Index");
            }
            return View(product);
        }

View :
@using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype= "multipart/form-data" }))
{
    
    @Html.EditorForModel();
    
    
Image
@if (Model.ImageData == null) { placehold } else { }
Upload new File
@Html.ActionLink("Cancel", "Index") }

這邊的重點在於
Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype= "multipart/form-data" })

必須先將 Form 宣告成 multipart,代表此「表單」包含多重欄位。詳細說明請參閱RFC 2388 。

PS:另外若非不得已請儘量避免在View中出現商業邏輯,如上方的  if   else ,這邊僅是方便文章作呈現。

參考資訊
蒋金楠(Artech)的博客
RFC 2388
mime-types-full
石頭閒語 --HTML 5 -File API 簡易教學

2013年5月28日 星期二

[Asp.net MVC] TempData、ViewData、ViewBag

若要將資料從後端Controller傳遞到View,除了使用ViewModel以外,最常見的就是底下三種:

1.ViewData
存放在物件中,生命週期為一個頁面。
Controller :
 public ActionResult Index()
        {
            ViewData["message"] = "訊息";
            return View();
        }
View :
@ViewData["message"]
2.ViewBag
這是MVC 3 之後新增的,使用方式和ViewData一樣,差別在於ViewBag 使用 dynamic 型別,可免去手動轉型的麻煩,使用上較為方便,但也因為動態型別關係,速度上會略比ViewData來的慢(人體無感吧@@)。
Controller :
 public ActionResult Index()
        {
            ViewBag.message = "訊息";
            return View();
        }
View :
@ViewBag.message
3.Temp Data
資料會儲存在Session 中,其生命週期為一個 Request,一旦Request結束就會被刪除。 因此我們可善用此特性讓資料跨不同Action傳遞至View,如RedirectToAction 中作使用,範例如下:




Controller :
        public ActionResult Index()
        {
            TempData["status"] = "我是從index送過來的!";
            return RedirectToAction("about");
        }

        public ActionResult about()
        {
            return View();
        }
View :

TempData :

@TempData["status"]
我們在Index Action 中使用了 RedirectToAction("about"),最後回傳 about.cshtml 這個View

為了證實TempData僅存活在一個Request中,我們對Browser按下F5,畫面會變成 :
"我是從index送過來的" 這訊息消失了!! TempData 確實已經被刪除。




更詳細的說明,可參考以下網站 : 

另外關於 RedirectToAction 所引發的 Http 302 可參考以下 :