2013年12月9日 星期一

[C#] 多個HTTP Post 方法在同一個Web API controller

多個HTTP Post 方法在同一個Web API controller

最近又要開始寫Http服務, 先前在某個route(或說某個Controller)下,只會針對單一種Request內容作處理,這次則設計成在同一個route下處理多種不同的Request

1.  一開始異想天開的寫個interface 當成POST方法的參數,結果因為送出的Request欄位會超出interface的定義,結果失敗~

2.  接下來也是很天真地寫上兩個POST方法在同一個Controller,結果出現route下有兩個POST方法造成無法識別要使用哪個方法的錯誤 ~____~ 

3.  最後終於利用的方法解決:
u  打開(App_Start\WebApiConfig.cs),修改WebApiRoute的預設設定:

config.Routes.MapHttpRoute(
       name:
"DefaultApi",
       routeTemplate:
"api/{controller}/{action}/{id}",
       defaults:
new { action = "Default", id = RouteParameter.Optional });

這邊可以看到我們將原本的Route : api/{controller}/{id}
修改為:api/{controller}/{action}/{id}
另外再加入為了要多個POST方法的Route設定:

config.Routes.MapHttpRoute(
       name:
"TransApi",
       routeTemplate:
"api/{controller}/{action}/{id}",
       defaults:
new { id = RouteParameter.Optional },
      
constraints: new { action="XXX|YYY|ZZZ" }
);

=>
這邊設定指定的action必須是XXX or YYY or ZZZ or …

u  接下來是最麻煩的部分,原本Controller中的所有CRUD方法都必須另外指定Route中的action name

例如 GET 方法,將action name設定為Default
[HttpGet,ActionName("Default")]

至於POST方法,就可以用action name區別不同的Route路徑:
[
HttpPost,ActionName("XXX")]
public C Post(A item)
{ }

[
HttpPost,ActionName("YYY")]
public C Post(B item)
{ }

4.  實際Call http service時,必須以我們新設定的Route的網址,例如假設我們的Controller名稱為ValueController

http://localhost/MyApi/Value  (Get,
沒有影響)

2013年12月6日 星期五

我只想用TFS做一般的文件管理~!

今天突然遇到 "如何在沒有安裝Visual Studio的機器上使用TFS" 這個問題 (驚!

每天一開電腦就是打開Visual StudioCoder,應該沒想過這個問題吧-_____-

還好Microsoft有提供 TFS Explorer的獨立安裝,可以不用安裝VS也可以使用TFS Explorer

另外文件做簽入簽出,有的時候還要打開 TFS Explorer有點小麻煩,這時候可以安裝Team Fundation PowerTool 直接在Windows Explorer上右鍵裡使用TFS的功能 ~



Design Pattern : Interpreter

Design Pattern : Interpreter

Definition :
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language



Original Context:原始翻譯前的內容
Interpreted Context:翻譯後的內容
IExpression:定義Interpret翻譯方法
ExpressionA & B
:實作Interpret翻譯方法

底下是將原本一長串的字串資料翻譯成Customer物件


1.  IExpression

public interface IExpression
{
 
Customer Interpret();
}

2.  Customer

public class Customer:IDisposable
{
   
public String Name { get; set; }
   
public int Age { get; set; }
   
public String PhoneNumber { get; set; }
   
public String Address { get; set; }
}

3.  ExpressionA

public class ExpressionA:IExpression
{
   
private String content = String.Empty;
   
public ExpressionA(String info)
    {
      
this.content = info;
    }
   
public Customer Interpret()
    {
      
using(Customer customer = new Customer())
       {
          customer.Name =
this.content.Substring(0, 5).Trim();
          customer.Age =
int.Parse(this.content.Substring(5, 3).Trim());
          customer.PhoneNumber =
this.content.Substring(8, 15).Trim();
          customer.Address =
this.content.Substring(22, 50).Trim();
         
return customer;
       }
    }
}

4.  主程式:
String name = "JB";
int age = 32;
String phoneNum = "0933-XXX-XXX";
String addr = "Taipei City, Neihui Street";

String info = String.Format("{0,-5}{1,3}{2,-15}{3,-50}", name, age.ToString(),phoneNum,addr);

Console.WriteLine("收到的原始資料:{0}", info);

IExpression exp = new ExpressionA(info);
Customer jb = exp.Interpret();

Console.WriteLine("姓名:{0}", jb.Name);
Console.WriteLine("年齡:{0}", jb.Age);
Console.WriteLine("電話號碼:{0}", jb.PhoneNumber);
Console.WriteLine("住址:{0}", jb.Address);

結果:
收到的原始資料:JB    320933-XXX-XXX   Taipei City, Neihui Street

姓名:JB
年齡:32
電話號碼:0933-XXX-XXX
住址:Taipei City, Neihui Street

=>
可以看到原本收到的是一串的資料,經過Interpreter之後,翻譯成一個可用的物件了。


5.  Reference

2013年12月2日 星期一

[Entity Framework 6] Issue (1)

.NET   Entity Framework    ORM

背景

前幾天把專案的Entity Framework升級到6.0.1後,原本run-time從其他dll注入的Connection雖然可以編譯成功,也可以建立Entity的連線,但是下Linq查詢時馬上throw 一個必須提供正確的Provider名稱的Exception 明明已經提供了System.Data.SqlClientProvider name  ( lol )

解決方式

最後,我把注入的Connection的來源專案,也另外升級到6.0.1 就成功了
(
應該版本不同,造成EF6無法辨識舊版的Connection)


另外新版的Entity Framework在建立Entity後,只會預設有一個constructor

[
你的Entity名稱].Context.cs
public XXXEntities() : base("name=XXXEntities")
{
}

所以如果要run-time丟入一個EntityConnection,必須手動加入繼承 DbContext 另外一個overloading constructor :

public XXXEntities(DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{}

MSDN參數定義
existingConnection
型別:System.Data.Common.DbConnection
要用於新內容的現有連接。

contextOwnsConnection
型別:System.Boolean
如果設定為 true,則處置內容時也會處置此連接,否則呼叫端必須處置此連接。