2016年12月1日 星期四

將副檔名為 .ashx 的 API 改為 RESTful 路由 / Change the API named .ashx to RESTful.

在公司接到了一個需求,就是將副檔名為「.ashx」的 api,路徑改為「~/{Dir}/XXX/」的格式,
簡單說就是要把副檔名拿掉,而這些API很單純,全都是POST,廢話不多說,看code吧。
(下面以VB.NET為範例)

1、在 Global.asax 修改下列程式:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    ' 在應用程式啟動時引發
    RegisterRoutes(RouteTable.Routes)
End Sub

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
    routes.Add("Item", New Route("{model}", New CompactRESTRouteHandler()))
    routes.Add("Directory", New Route("{directory}/{model}"
                          , New CompactRESTRouteHandler()))
End Sub
2、建立一個檔案:CompactRESTRouteHandler.vb
Friend Class CompactRESTRouteHandler
    Implements IRouteHandler

    Public Function GetHttpHandler(requestContext As RequestContext) 
                 As IHttpHandler Implements IRouteHandler.GetHttpHandler

        Dim RouteData = requestContext.RouteData
        '取出參數
        Dim directory As String = Convert.ToString(RouteData.Values("directory"))
        Dim model As String = Convert.ToString(RouteData.Values("model"))
        Dim id As String = Convert.ToString(RouteData.Values("id"))

        If String.IsNullOrEmpty(directory) = False Then
            HttpContext.Current.Items.Add("directory", directory)
        End If
        HttpContext.Current.Items.Add("model", model)
        If String.IsNullOrEmpty(id) = False Then
            HttpContext.Current.Items.Add("id", id)
        End If
        '檢查看看有無該Model對應的ASHX?
        Dim ashxName As String = Path.Combine(directory, model + ".ashx")
        '找不到對應的ASHX
        'If File.Exists(HostingEnvironment.MapPath("~/" + ashxName)) = False Then
        '    Return CType(BuildManager.CreateInstanceFromVirtualPath("~/NotFound.aspx", GetType(Page)), Page)
        'End If

        '導向指定的ASHX
        Return CType(BuildManager.CreateInstanceFromVirtualPath("~/" + ashxName, GetType(IHttpHandler)), IHttpHandler)
    End Function

End Class
參考文章: 逐步解說:在 Web Form 應用程式中使用 ASP.NET 路由逐步解說:在 Web Form 應用程式中使用 ASP.NET 路由 RESTful探索3-ASP.NET 3.5 Routing for REST

2016年9月21日 星期三

MVC API 要傳遞複雜型別參數時,要同時支援 GET 及 POST 的解決方案 / When pass complex type parameters on MVC API, to support both "GET" and "POST" solution.

有時候我們在寫 API 的時候,會有奇怪的需求,
帶入複雜型別的參數,來 GET 資料,
以下說明如何用 WebApiContrib 套件來達成這個目的。

1. 透過 NuGet 取得 WebApiContrib 套件。
2. 加上 Using
using WebApiContrib.ModelBinders;
3. 於API Controller 加上 attribute
[MvcStyleBinding]
4. 加上動作方法
[HttpGet, HttpPost]
這樣就可以囉!

2016年7月22日 星期五

如何設定 CORS,以偷雞的方式來允許所有的 Domain / How to set CORS use unusual way to allow all domain ?

試了很多方式,即使將 Access-Control-Allow-Origin 設為「*」,也是無法順利的跨網域存取,
只好用偷雞的方式,將每一個 Request 的 Origin,加到 Access-Control-Allow-Origin,
算是另類的允許所有 Domain。

WebApiConfig.cs:
config.EnableCors();
Global.asax.cs:
protected void Application_BeginRequest(object sender, EventArgs e)
{
    //允許所有的domain
    string clientOrigin = HttpContext.Current.Request.Headers["Origin"];
    if (!string.IsNullOrEmpty(clientOrigin))
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin"
                                              , clientOrigin);
    }
}

2016年7月20日 星期三

C# .NET如何取得星期 / How to get chinese week from C# .NET ?

.NET 有內建一個可以簡單取得「星期」的語法,
一行而已,如下:
DateTimeNow().ToString("ddd", new System.Globalization.CultureInfo("zh-TW"));
結束。

如何使用模版引擎 - NVelocity? / How to use NVelocity ?

在某一個專案中,有一個要以 HTML 寄送電子報的需求,
於是找到了 NVelocity 的套件,這個套件在 NuGet 內可以找到,
下面會說明如何使用。

首先新增一個 Method 如下:
/// <summary>
/// 將資料套入範本檔
/// </summary>
/// <param name="templateLocation">套表範本路徑(不含檔名)</param>
/// <param name="templateName">套表範本檔名</param>
/// <param name="encoding">語系</param>
/// <param name="model">帶入套表的參數</param>
/// <returns>Html file</returns>
public string MergeTemplate(string templateLocation
                          , string templateName
                          , string encoding
                          , Hashtable model)
{
    // 初始化並取得Velocity引擎 
    VelocityEngine ve = new VelocityEngine();
    ve.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH
                 , HttpContext.Current.Request.MapPath(string.Format("~/{0}/"
                                                     , templateLocation)));
    ve.Init();

    Template t = new Template();
    // 取得velocity的模版 
    t = ve.GetTemplate(templateName, encoding);

    // 取得velocity的上下文context 
    VelocityContext context = new VelocityContext(model);

    // 輸出流 
    StringWriter writer = new StringWriter();

    // 轉換输出 
    t.Merge(context, writer);

    string r = writer.ToString();
    writer.Flush();
    writer.Close();

    return r;
}

用法:
●C# 語法:
string templateLocation = "vm"      //範本檔路徑
string templateName = "temp.html"   //範本檔名稱
string encoding = "UTF-8"           //編碼
Hashtable model = new Hashtable     //參數
model.Add("header", "test header")  //「header」是html檔案要套用的參數名稱
                                    //「test header」是參數內的值
VelocityHelper velocityHelper = new VelocityHelper();
string html = velocityHelper.MergeTemplate(templateLocation
                                         , templateName
                                         , encoding
                                         , model);

●範本檔(html)的部份
在要套上參數的地方名稱加上「$」即可,如:「$header」
而這個名稱要跟 C# 程式碼的名稱對應。

參數也可以用物件帶入:
●C# 語法:
public class HeaderModel
{
     public string text;
     public string value;
}
HeaderModel hm=new HeaderModel();
model.Add("header", hm);

●範本檔(html)的部份:
$header.text
$header.value

2016年7月18日 星期一

如何利用 ASP.NET 的 FormsAuthentication 來做表單驗證 / How to use FormsAuthentication of ASP.NET ?

在Web.Config中加入下列參數
  
<system.web="">
    <authentication mode="Forms">
      <!--defaultUrl:登入後到哪一頁,loginUrl:使用者未登入的話,要導至哪一頁-->
      <forms defaulturl="Default.aspx" loginurl="Login.aspx" timeout="30">
    </forms></authentication>
</system.web>

讓會員登入成「已驗證」狀態:
FormsAuthentication.RedirectFromLoginPage("Henry", True);

執行這段程式碼後,就會以「Henry」定義的名稱登入了。

登入後,要如何判斷使用者已經是登入的狀態?
C#:User.Identity.IsAuthenticated
VB:My.User.IsAuthenticated

登入後,要如何取得已登入的帳號?
C#:User.Identity.Name
VB:My.User.Name

2016年7月4日 星期一

如何使用 GetField 來動態取得或設定物件的值 / How do I use "GetField" to dynamically get or set the value of an object ?

先前在某一個情境下,需要動態來取得或設定某個物件的值。
假設有一個 Class 如下:
public class TestObject()
{
    string A1;
    string A2;
    string A3;
}

如上面的 Class,我要用變數來存取 TestObject 內的 A2 的值。

這時候要怎麼做呢?

先初始化物件,這大家應該都會的:
TestObject testObject = new TestObject();

然後宣告這個 Object 的 Type:
Type testType = testObject.GetType();

接下來就可以順利的取得 testObject.A2 的值:
string val = (string) testType.GetField("A2").GetValue(testObject);

如果要變更 testObject.A2 的值也是可以:
testType.GetField("A2").SetValue(testObject, "new value");

Surface pro 6降頻至0.4GHz的解決方式

網路查到很多都說: 按住電源鍵30秒關機、再同時按住電源鍵+音量上鍵15秒重啟,解決。 實際試過是有效,但某一天看到當配件溫度過高,也是會造成降頻的原因之一, 索性就把電源線拔掉,神奇的事情發生了~~ cpu頻率就正常了 。 但其實當下電源供應器並沒有發熱的現象,只...