2013-11-20 4 views
0

Какая официальная MS или лучшая архитектура для проектирования веб-API, который принимает сложный тип и возвращает сложный тип?Веб-API, который принимает сложный тип и возвращает сложный тип?

Сложность: Передача сложных типов по HTTP без ссылки на центральный тип данных во время пребывания RESTful.

В настоящее время: Я делаю это успешно, но спорю с моим начальником о лучшей практике, и если я сделал это правильно. Microsoft утверждает, что вы можете передать сложный тип, как параметр с атрибутом [FromBody], но мне не повезло с этим (рабочий пример со сложным типом был бы замечательным).

Тип Знание модели: Клиентское приложение и веб-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; 
    } 

Routing

 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

Что такое официальная MS или лучшая практика архитектуры для проектирования веб-API , который принимает сложный тип и возвращает сложный тип?

Услуги веб-API - это веб-службы REST. Существует набор принципов REST. После ссылки ниже, помогут вам понять их

  1. Статья о Richardson Maturity Model от Мартина Фаулера http://martinfowler.com/articles/richardsonMaturityModel.html
  2. Видео презентация из Осло NDC о принципах REST http://vimeo.com/43808786

Web API ASP.NET только один технологий, с помощью которых вы можете внедрять сервисы REST. Подробнее о функциях и передовых методах вы найдете на презентации конференции Build 2013 о ASP.API NET Web http://channel9.msdn.com/Events/Build/2013/3-504

Сложность: Передача сложных типов через HTTP без ссылки на центральный тип данных во время пребывания RESTful Согласно принципам выше сделайте следующее:

  1. использовать различные HTTP Глаголы и носителей. Наиболее широко используются GET, POST, PUT, DELETE. Они отлично отображают операции CRUD. GET = read, POST = create, PUT = update, DELETE.
  2. Глаголы ограничивают вас способом передачи сложных данных. Все глаголы, кроме GET, используют тело сообщения HTTP, тело сообщения HTTP не разрешено в GET в соответствии со стандартом HTTP. Не сложно получить сложный тип данных с сервера в теле, например, в виде сериализованной строки JSON, для запросов, кроме GET, также не проблема использовать JSON для сложных типов в теле
  3. Когда вы имеете дело с GET и не имеют возможности передавать сложный тип данных в виде строки JSON в теле сообщения HTTP - вам нужно тщательно в соответствии с REST создавать свои URL-адреса. Например, у меня есть пользовательский ресурс, который я хочу получить у пользователя. У меня нет другого способа передать эти данные либо с помощью заголовков HTTP, либо через строку URL. Затем используйте идентификатор для ваших ресурсов. Чтобы получить этого пользователя, я передам его через URL http://myapp.com/users/179067, где идентификатор 179067 для пользовательского ресурса, он может быть идентификатором пользователя в БД или некоторым идентификатором, сопоставленным с пользователем, который однозначно идентифицирует его.

Или еще один образец. Мне нужно получить пользователя, который был создан до 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

Смежные вопросы