2013-11-20 72 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