利用swagger建立互動式API文件

2015年12月28日 星期一

最近在寫Web API程式,通常都會搭配Help Page來使用,可以建立文件方便查詢,但是如果要測試API,則都會使用Fiddle或是PostMan來做測試,同事有介紹我一套叫Swagger的套件,它不只能產生文件,也可以在網頁上直接測試,是不是超棒的,以下是記錄我安裝的過程以及使用方法,我是用新專案來做範例


1.建立新專案
2.選擇Web API
3.使用NuGet來下載Swagger套件


4.安裝完成後,在專案上按右鍵,選擇屬性

5.選擇產生文件要放置的地方

6.開啟App_Start\SwaggerConfig.cs,打開註解處

7.實作GetXmlCommentsPath()方法

8.測試時,只要執行網站並在後面輸入\swagger即可開始頁面

9.可直接展開方法,並做測試,執行後可看到結果





以上就是基本的swagger套件使用方式。
最後附近github位址:https://github.com/domaindrivendev/Swashbuckle

Read more...

為Enum加入取得Description Extension方法

2015年12月22日 星期二

在使用Enum時,有時候需要定義說明文字以利在UI上呈現,所以可以加入屬性Description,於是在網路上找了一下,結果只有找到取得名稱的方式,如下所示
 
using System;

public class GetNameTest {
    enum Colors { Red, Green, Blue, Yellow };
    enum Styles { Plaid, Striped, Tartan, Corduroy };

    public static void Main() {
        Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), 3));
        Console.WriteLine("The 4th value of the Styles Enum is {0}", Enum.GetName(typeof(Styles), 3));
    }
}


來源:https://msdn.microsoft.com/zh-tw/library/system.enum.getname(v=vs.110).aspx


所以只好自已寫擴充方法來新增

 
public static class HelpExtensions
{
 public static string GetEnumDescription(this Enum value)
 {
  FieldInfo fi = value.GetType().GetField(value.ToString());

  DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
  //若取不到屬性,則取名稱
  if ((attributes != null) && (attributes.Length > 0))
   return attributes[0].Description;
  else
   return value.ToString();
 }
}

public enum MessageType
{
    [Description("Create")]
    Creation = 1,
    [Description("Update")]
    Updating = 2,
    [Description("Del")]
    Deletion = 3,
    [Description("Select")]
    Selection = 4
}

//使用方式
var messageType = MessageType.Deletion.GetEnumDescription();
Console.WriteLine("Ouput:" + messageType);
//顯示結果
//Output:Del

Read more...

手動註冊window service程式

2015年10月6日 星期二

執行程式如下:


加入service方式
c:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe C:\xxx\xxx.exe(執行程式名稱)

刪除service 
sc delete service名稱

Read more...

指令編譯C#

2015年8月5日 星期三

查詢指令

csc /help

編譯cs檔方式

C:\Windows\Microsoft.NET\Framework\v4.0.30319>csc /t:exe /out:c:\helloworld\hell
oworld.exe c:\helloworld\helloworld.cs

 

 

public class HelloWorld
{
    public static void Main(string[] args)
    {
        System.Console.WriteLine("Hello World!");
        System.Console.ReadLine();
    }
}

Read more...

Guid.NewGuid Enter Web Address is not work IE8

2015年7月12日 星期日

今天遇到使用Guid.NewGuid在IE8的奇怪問題
如果在網站列按Enter則會發生,但按F5重新整理確不會
最後確定是瀏覽器Cache問題造成的,我來重現一下實際的情況

測試程式如下:

 
protected void Page_Load(object sender, EventArgs e)
{
    Response.Write(Guid.NewGuid().ToString() );
}


這是個很簡單的產生Guidd語法,當IE8瀏覽器設定如下時:

則會發生Guid不會改變的情況,如下圖



解決方式:

Client端設定,不是個好方法。
比較好的解決 Server 端處理加入除清Cache語法,這樣就不會有Cache的問題囉


 
protected void Page_Load(object sender, EventArgs e)
{
    Response.Cache.SetNoStore(); //清除Cache
    Response.Write(Guid.NewGuid().ToString() );
}

Read more...

site map 取得自訂屬性

2015年6月23日 星期二

 

public class SiteMapMenu : HierarchicalDataBoundControl
{
  public void RecursiveCreateChildControls(IHierarchicalEnumerable dataItems, bool isRecursiveCall)
  {
      //抓取自訂屬性
      System.Web.SiteMapNode node = dataItem.Item as System.Web.SiteMapNode;
      bool customerTag = node["coustomerFlag"];

      if(customerTag) continue;
  }

}

//Web.sitemap


參考:https://msdn.microsoft.com/zh-tw/library/system.web.sitemapnode(v=vs.110).aspx

Read more...

將datareader取出資料轉成Enum型態

2015年3月29日 星期日

(CreationStatus)Enum.Parse(typeof(CreationStatus), dataReader["CreationStatus"].ToString());

 
private static List AddECEventLog(IDataReader dataReader)
{
 var ecEventLogList = new List();
 while (dataReader.Read())
 {
  var ecEventLog = new ECEventLog();
  ecEventLog.ECEventId = dataReader["ECEventId"] == DBNull.Value ? null : dataReader["ECEventId"].ToString();
  ecEventLog.CreationStatus = (CreationStatus)Enum.Parse(typeof(CreationStatus), dataReader["CreationStatus"].ToString());
  ecEventLogList.Add(ecEventLog);
 }
 return ecEventLogList;
}

Read more...

Func & Action 用法

2015年1月28日 星期三

Func & Action是委派用法,差別在於Func:有回傳值,Action:不需要回傳值

首先來看一下委派基本用法

 
    //委派基本定義
    public delegate string BaseDeletegate(string source);

    public static class ServiceBase
    {
        public static string Execute(BaseDeletegate action, string source)
        {
            string value = action.Invoke(source);
            return value;
        }
    }

    //呼叫委派用法
    public static void runBaseDeletegate()
    {
        BaseDeletegate action = ResponseMsg;
        string result = ServiceBase.Execute(action, "Neil");
        Console.WriteLine(result);
        Console.ReadLine();
    }

    //執行的方法
    public static string ResponseMsg(string str)
    {
        return "Hello:" + str;
    }
執行結果

改成用Func方法

 
    //Func定義
    public static string ExecuteFunc(Func action)
    {
        return action();  //有回傳值
    }

    //呼叫Func方法
    public static void runBaseFunc()
    {
        string result = ServiceBase.ExecuteFunc(() => {
            return ResponseMsg("FuncNeil");
        });
        Console.WriteLine(result);
        Console.ReadLine();
    }

    //執行的方法
    public static string ResponseMsg(string str)
    {
        return "Hello:" + str;
    }

執行結果:

改成用Action方法

 
    //Action定義
    public static void ExecuteAction(Action action)
    {
        action(); //沒有回傳值
    }

    //呼叫Action方法
    public static void runBaseAction()
    {
        ServiceBase.ExecuteAction(() => {
            ActionResopnseMsg("ActionNeil");
        });
    }

    //執行的方法
    public static void ActionResopnseMsg(string str)
    {
        Console.WriteLine("Hello:" + str);
        Console.ReadLine();
    }

執行結果:

Read more...

throw ex vs throw

2015年1月22日 星期四

寫了這麼久的程式,都沒特別注意到這二者的差別
簡單來說throw 會多一項原始執行錯誤行號。


  • throw ex resets the stack trace (so your errors would appear to originate from HandleException)
  • throw doesn't - the original offender would be preserved.


 
 static void Main(string[] args) {
  try {
   ThrowException1(); // line 19
  } catch (Exception x) {
   Console.WriteLine("Exception 1:");
   Console.WriteLine(x.StackTrace);
  }
  try {
   ThrowException2(); // line 25
  } catch (Exception x) {
   Console.WriteLine("Exception 2:");
   Console.WriteLine(x.StackTrace);
  }
 }

 private static void ThrowException1() {
  try {
   DivByZero(); // line 34
  } catch {
   throw; // line 36
  }
 }
 private static void ThrowException2() {
  try {
   DivByZero(); // line 41
  } catch (Exception ex) {
   throw ex; // line 43
  }
 }

 private static void DivByZero() {
  int x = 0;
  int y = 1 / x; // line 49
 }

輸出結果
Exception 1(throw):
at UnitTester.Program.DivByZero() in \Dev\UnitTester\Program.cs:line 49
at UnitTester.Program.ThrowException1() in \Dev\UnitTester\Program.cs:line 36
at UnitTester.Program.TestExceptions() in \Dev\UnitTester\Program.cs:line 19
Exception 2(throw ex):
at UnitTester.Program.ThrowException2() in \Dev\UnitTester\Program.cs:line 43
at UnitTester.Program.TestExceptions() in \Dev\UnitTester\Program.cs:line 25

Read more...

Group By 使用方法

2015年1月8日 星期四

最近遇到一個操作集合物件時,需要做群組的功能,以前都是在SQL裡操作

今天透過Linq的Group By方法來實作,順便記錄一下。


測試資料結構



Group By後結果



//放入測試資料
var testList = new List();
testList.Add("event1,s11,1");
testList.Add("event1,s12,1");
testList.Add("event1,s13,1");
testList.Add("event1,s14,1");
testList.Add("event1,s15,1");
testList.Add("event2,s21,1");
testList.Add("event2,s22,1");

//處理資料格式
var sourceList = new List>();
foreach (var item in testList)
{
    var querySplit = item.Split(',');
    string eventId = querySplit[0];
    string selectionId = querySplit[1];
    string handicap = querySplit[2];

    var list = new KeyValuePair(eventId, string.Format("{0}#{1}", selectionId, handicap));
    sourceList.Add(list);
}

//利用Group By 放入Dictionary物件裡
Dictionary> mList = sourceList.GroupBy(p => p.Key,p=>p.Value)
    .ToDictionary(p => p.Key, p => p.Select(s => s)
    .ToList());

最後呈現結果如下:

轉換完成後Dictionary的Key就是event,Value就是該Event下的記錄 。

參考來源:http://www.dotblogs.com.tw/lastsecret/archive/2011/02/18/21422.aspx

Read more...

傳值 vs 傳址

2015年1月5日 星期一

常常會搞不太清楚傳值以及傳址的差異,就先來筆記一下,以免以後忘記 開懷大笑

範例如下:

static void Main(string[] args)
{
//參考型別傳值(兩個變數位址不同)
TestClass y = new TestClass();
TestClass r1 = ChangeByVal(y);
Console.WriteLine("r1和y指向同實體:" + (r1 == y).ToString());
//參考型別傳址(兩個變數位址相同)
TestClass r2 = ChangeByRef(ref y);
Console.WriteLine("r2和y指向同實體:" + (r2 == y).ToString());
Console.ReadLine();
}
private static TestClass ChangeByVal(TestClass y)
{
y = new TestClass();
return y;
}
private static TestClass ChangeByRef(ref TestClass y)
{
y = new TestClass();
return y;
}


結果如下:

image

 

補充:這張圖可以說明兩個的不同處

pass-by-reference-vs-pass-by-value-animation

Read more...

使用var的場合

var 可用在暱名型別上,強型別或稱右(後)決議型別,只能做為宣告區域變數使用,一定要定義右邊的型態

編譯時期才做轉型



var x = new object();

//編譯時
object x = new object();


範例如下:



        
//使用var的場合
static void main(string[] args)
{
string[] words = { "apple","cherry","blueberry"};
var newwords = words.select(w => new { upper = w.toupper(), lower = w.tolower() });
foreach (var item in newwords)
{
console.writeline(item.lower + ":" + item.upper);
}
console.readkey();
}

Read more...