2013-11-20 164 views
0

設計Web API的官方MS或最佳體系結構實踐是什麼?它採用複雜類型並返回複雜類型?接受複雜類型並返回複雜類型的Web API?

難度: 傳遞複雜類型通過HTTP沒有參考到中央數據類型,同時保持RESTful的。

目前: 我成功地這樣做,但我的老闆介紹最佳做法爭論,如果我有正確的做到了這一點。微軟聲稱你可以傳入一個複雜的類型,就像一個[FromBody]屬性的參數,但我沒有任何運氣(一個複雜類型的工作示例將會很棒)。

類型模型的知識: 客戶端應用程序和Web API都必須包含類的中央庫的引用。圍繞這是使用WSDL來傳遞每個請求的類型信息,我的老闆不喜歡這樣,因爲我們將有庫DLL的不同彙編(從一個客戶端應用程序到下),我可以看到的唯一途徑(不理想在遠程位置移動,因此REST),任何建議。

目前代碼(工作):

控制器調用API

[Authorize] 
    public async Task<ActionResult> Index() 
    { 
      InstallerPinModel currentInstaller = new InstallerPinModel(); 
      currentInstaller.userName = "from Controller"; 
      Task<WebResponse> response = checkPinTime(currentInstaller);//checkPinTime calls API 

      //I found the following two lines are very helpful for debugging 
      //while(response.IsCompleted == false) 
       //Thread.Sleep(100); 

      Stream responseResultsStream = response.Result.GetResponseStream(); 
      int responseResultContentLength = (int)response.Result.ContentLength; 
      byte[] responseResultContentAsBytes = new byte[responseResultContentLength]; 
      responseResultsStream.Read(responseResultContentAsBytes, 0, responseResultContentLength);//Pull Data Stream into Byte[] responseResultContentAsBytes 
      string responseResultsAsString = System.Text.Encoding.UTF8.GetString(responseResultContentAsBytes); 
      JavaScriptSerializer serializesJS = new JavaScriptSerializer(); 
      currentInstaller = serializesJS.Deserialize<InstallerPinModel>(responseResultsAsString); 
      if(currentInstaller.userName == "from API") 
       returnView = GoalView; 
      else 
       returnView = TimedOutView; 
     } 
     return View(); 
    } 

public Task<WebResponse> checkPinTime(InstallerPinModel incomingUser)//Function to call Post Web API 
    { 
     string requestData = new JavaScriptSerializer().Serialize(incomingUser);//Just slightly different syntax 
     ASCIIEncoding encoding = new ASCIIEncoding(); 
     byte[] requestDataAsBytes = encoding.GetBytes(requestData); 
     WebRequest request = WebRequest.Create("http://localhost:51366/api/InstallerPin"); 
     request.Method = "POST"; 
     request.ContentLength = requestDataAsBytes.Length; 
     request.ContentType = "application/x-www-form-urlencoded"; 
     Stream requestDataStream = request.GetRequestStream(); 
     requestDataStream.Write(requestDataAsBytes, 0, requestDataAsBytes.Length); 
     requestDataStream.Close(); 
     Task<WebResponse> response = request.GetResponseAsync(); 
     return response; 
    } 

的Web API

public async Task<HttpResponseMessage> Post() 
    { 
     //ReadIncoming 
     InstallerPinModel incomingInstallerPIN = new InstallerPinModel(); 
     Task<byte[]> requestContentByteArray = Request.Content.ReadAsByteArrayAsync(); 
     ASCIIEncoding encoding = new ASCIIEncoding(); 
     string requestContentAsString = encoding.GetString(await requestContentByteArray); 
     JavaScriptSerializer serializesJS = new JavaScriptSerializer(); 
     incomingInstallerPIN = serializesJS.Deserialize<InstallerPinModel>(requestContentAsString); 

     //This is where the post would take place 
     //Send Responspe Object 
     InstallerPinModel outgoingInstallerPIN = new InstallerPinModel(); 
     outgoingInstallerPIN = incomingInstallerPIN; 
     outgoingInstallerPIN.userName = "from API"; 


     //BuildOutgoing 
     string responseAsString = serializesJS.Serialize(outgoingInstallerPIN); 
     StringContent responseContent = new StringContent(responseAsString); 
     await responseContent.LoadIntoBufferAsync(); 
     HttpResponseMessage returnableResponseMessage = new HttpResponseMessage(); 
     returnableResponseMessage.Content = responseContent; 
     return returnableResponseMessage; 
    } 

路由

 config.Routes.MapHttpRoute(
      name: "noParamsInURL", 
      routeTemplate: "api/{controller}", 
      defaults: new { } 
     );//Route for InstallerPinController 

     //(Default) Route for standard API Controllers 
     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}/{application}", 
      defaults: new { id = RouteParameter.Optional, application = RouteParameter.Optional }); 

類型型號

public class InstallerPinModel 
{ 
    public string userName {get; set;} 
    public int pin {get; set;} 
    public int newPin { get; set; } 
} 

請確保在API和客戶端應用程序中都包含對類型模型的引用。

回答

0

設計 Web API的官方MS或最佳體系結構實踐是什麼?它採用複雜類型並返回複雜類型?

的Web API服務是REST Web服務。有一套REST原則。下面以下鏈接將幫助您瞭解他們

  1. 文章關於理查德森成熟度模型從Martin Fowler的http://martinfowler.com/articles/richardsonMaturityModel.html
  2. 從奧斯陸NDC
  3. 視頻演示關於REST原則http://vimeo.com/43808786

的ASP.NET Web API只有一個與幫助的技術,其中可以實現REST服務 更多功能和最佳做法是從構建2013會議有關ASP的介紹。NET的Web API http://channel9.msdn.com/Events/Build/2013/3-504

難度:傳遞複雜類型通過HTTP沒有參照 中央數據類型,而住的RESTful 根據原則上面做如下:

  1. 使用不同的HTTP動詞媒體類型。最廣泛使用的GET,POST,PUT,DELETE。它們完美地映射到CRUD操作。 GET =讀取,POST =創建,PUT =更新,刪除。
  2. 動詞限制了你如何傳遞複雜的數據。除GET之外的所有動詞都使用HTTP消息體,根據HTTP標準,HTTP消息體不允許在GET中使用。從主體中的服務器獲取複雜數據類型(例如以串行化JSON字符串的形式)對於獲取除GET以外的請求也不是問題,對於在主體中使用複雜類型的JSON也不是問題
  3. 當您處理GET並且沒有機會在HTTP消息體中將複雜數據類型作爲JSON字符串傳遞 - 您需要根據REST設計仔細根據您的URL。例如我有用戶資源我想要得到的用戶我沒有其他的方式來使用HTTP頭或通過URL字符串傳遞這些數據。然後爲你的資源使用標識符。爲了得到這個用戶,我將通過URL http://myapp.com/users/179067傳遞它,其中179067用戶資源的標識符,它可以是DB中的用戶標識符或某個標識符映射到唯一標識它的用戶。

或另一個樣本。我需要獲得2000年前創建的用戶和德國的用戶。此示例與查詢類似,我將使用ODATA語法 - http://myapp.com/users?$filter=Country eq 'germany' and Created le 01.01.200。難道不怕約空格或引號,它們將被編碼爲%20或27%

,當你需要WSDL或試圖重塑WSDL則可能是REST是不適合你。然後使用anz其他的WS - */SOAP技術,例如WCF