Web API采用复杂类型并返回复杂类型?

时间:2013-11-20 20:36:59

标签: c# asp.net-web-api

设计采用复杂类型并返回复杂类型的Web API的官方MS或最佳架构实践是什么?

难度:         在保持RESTful的同时,通过HTTP传递复杂类型而不引用中央数据类型。

目前:     我成功地这样做了,但是和我的老板争论最佳做法,如果我做得对的话。微软声称你可以传递一个复杂的类型,就像一个带有[FromBody]属性的参数一样,但是我没有运气(一个复杂类型的工作示例会很精彩)。

类型模型知识:     客户端应用程序和Web API都引用了包含类的中央库。我的老板不喜欢这个,因为我们将有不同的库DLL汇编(从一个客户端应用程序到下一个),我能看到的唯一方法是使用WSDL传递每个请求的类型信息(不理想)对于移动设备在远程位置,因此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和客户端应用程序中包含对Type Model的引用。

1 个答案:

答案 0 :(得分:0)

  

设计a的官方MS或最佳架构实践是什么?   Web API采用复杂类型并返回复杂类型?

Web API服务是REST Web服务。有一组REST原则。以下链接将帮助您理解它们

  1. 关于Martin Fowler的{Richerdson成熟度模型的文章http://martinfowler.com/articles/richardsonMaturityModel.html
  2. 奥斯陆国家数据中心关于REST原则http://vimeo.com/43808786
  3. 的视频演示

    ASP.NET Web API只是可以帮助您实现REST服务的技术之一 有关功能和最佳实践的更多信息,请参阅Build 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标准,GET中不允许HTTP消息体。从正文中的服务器获取复杂数据类型不是问题,例如以序列化JSON字符串的形式,对于除GET之外的请求,对于正文中的复杂类型使用JSON也不是问题
    3. 当您处理GET并且没有机会在HTTP消息正文中将复杂数据类型作为JSON字符串传递时 - 您需要仔细根据REST设计您的URL。例如,我有用户资源我想要获取用户我无法使用HTTP标头或URL字符串传递此数据。然后使用标识符为您的资源。要获得此用户,我将通过URL http://myapp.com/users/179067传递它,其中179067是用户资源的标识符,它可以是数据库中的用户ID,也可以是映射到用户的一些ID,用于唯一标识它。
    4. 或另一个样本。我需要获得在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

相关问题