title: Web API that takes in a complex type and returns a complex type?
body: <p>What is the official MS or best architecture practice for designing a Web API that takes in a complex type and returns a complex type?</p>
  
  <p>Difficulty:
          Passing complex types over HTTP without a reference to a central data type while staying RESTful.</p>
  
  <p>Currently:
      I am doing this successfully, but arguing with my boss about the best practice and if I have done this correctly.  Microsoft claims you can pass in a complex type just like a parameter with a [FromBody] attribute but I haven't had any luck with this(a working example with a complex type would be wonderful).</p>
  
  <p>Type Model Knowledge:
      The client application and Web API both have a reference to a central library that contains a class.  My boss doesn't like this as we will have different compilations of the library DLL(from one client application to the next), the only way I can see around this is to use WSDL to pass the type information on each request(not ideal for mobile in remote locations, hence REST), any suggestions.</p>
  
  <p>Current Code(working):</p>
  
  <p>Controller Calling API</p>
  
  <pre><code>[Authorize]
      public async Task&lt;ActionResult&gt; Index()
      {
              InstallerPinModel currentInstaller = new InstallerPinModel();
              currentInstaller.userName = "from Controller";
              Task&lt;WebResponse&gt; 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&lt;InstallerPinModel&gt;(responseResultsAsString);
              if(currentInstaller.userName == "from API")
                  returnView = GoalView;
              else
                  returnView = TimedOutView;
          }
          return View();
      }
  
  public  Task&lt;WebResponse&gt; 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&lt;WebResponse&gt; response = request.GetResponseAsync();
          return response;
      }
  </code></pre>
  
  <p>Web API</p>
  
  <pre><code>    public async Task&lt;HttpResponseMessage&gt; Post()
      {
          //ReadIncoming
          InstallerPinModel incomingInstallerPIN = new InstallerPinModel();
          Task&lt;byte[]&gt; requestContentByteArray = Request.Content.ReadAsByteArrayAsync();
          ASCIIEncoding encoding = new ASCIIEncoding();
          string requestContentAsString = encoding.GetString(await requestContentByteArray);
          JavaScriptSerializer serializesJS = new JavaScriptSerializer();
          incomingInstallerPIN = serializesJS.Deserialize&lt;InstallerPinModel&gt;(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;
      }
  </code></pre>
  
  <p>Routing</p>
  
  <pre><code>        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 });
  </code></pre>
  
  <p>Type Model</p>
  
  <pre><code>public class InstallerPinModel
  {
      public string userName {get; set;}
      public int pin {get; set;}
      public int newPin { get; set; }
  }
  </code></pre>
  
  <p>Make sure to include references to Type Model in both the API and Client Application.</p>