Как передать STRUCT - ИЛИ - JSON методу CFC в Coldfusion - PullRequest
6 голосов
/ 29 февраля 2012

У меня есть существующий CFC, который отлично работает при передаче структур в метод.

Проблема в том, что теперь нам также нужно передать данные в ту же функцию через JSON.

Вот фрагмент кода CFC:

<cffunction 
  name="subscribeAPI" 
  access="remote" 
  returntype="struct" 
  returnformat="json" 
  output="false">

  <cfargument 
    name="structure" 
    type="struct" 
    required="true" 
    hint="data structure received from call">

<cfif StructKeyExists(arguments.structure, "listID") 
  AND len(arguments.structure.listID)>
 ...
</cfif>

<cfreturn LOCAL />

Вот как мы передаем структуру:

<cfset preStruct = {
  apiAction="Create",
  listID="1463",
  email="#form.cartEmail#",
  firstname="#form.first_name#",
  preCart="#now()#",
  planDescription="#application.name.site#"
  }
/>

<cfscript>voidReturn = application.goxObj.subscribeAPI(preStruct);</cfscript>

Теперь нам также нужно пройтив следующем, но, очевидно, получаются ошибки из-за того, что CFC ожидает структуру:

function HandleSubscribe(){
  $j.getJSON(
    "/com/list.cfc?wsdl",
    {
      method : "subscribeAPI",
      action : "Create",
      listID : $j( "#listID" ).val(),
      triggerKey : $j( "#triggerKey" ).val(),
      email : $j( "#emailNL" ).val(),
      firstname : $j( "#firstnameNL" ).val()
    },
  handleSubscribeCallback
);

}

Как мы можем успешно передать фрагмент getJSON?

Спасибо.

Ответы [ 3 ]

3 голосов
/ 29 февраля 2012

JSON - это просто строка, поэтому вам нужно «обработать» вызов метода до того, как он достигнет фактического уровня обслуживания.

Danimal прав в том, что вам нужно создать оболочку слоя веб-службы вокруг вашей службы.

Итак, ваш метод обслуживания выглядит следующим образом:

<cffunction name="CreateSubscription" access="public" returntype="struct" output="false">
    <cfargument name="listID" required="true" type="numeric">
    <cfargument name="emailaddress" required="true" type="string">
    <cfargument name="firstname" required="true" type="string">

    <cfset var resultset = {success=false}>

    <!--- Validate your listid and subscription details --->
    <!--- If Valid Then insert subscription --->
    <cfset resultset.success = true>

    <!--- else --->
    <cfset resultset.message = 'kerboom!'>

    <!--- only return what you need as a struct, not the whole local scope! --->
    <cfreturn resultset />
 </cffunction>

Ваш API подписки выглядит так:

<cffunction name="subscribeAPI" access="remote" returntype="struct" returnformat="json" output="false">

   <cfargument name="JSONPacket" type="string" required="true" hint="data structure received from call">
   <cfset var incomingData = deserializeJSON(arguments.JSONPacket)>
   <cfset var resultset = {success=false,message='invalid data'}>

   <cfif StructKeyExists(incomingData, "apiAction")>
       <cfif incomingData.apiAction EQ "create">
           <!--- You should also check you have the required fields for the createSubscription method here too. --->
           <cfset resultset = subscriptionService.createSubscription(incomingData)>
       </cfif>
   <cfelse>
       <cfset resultset.message = 'No API Action specified'>
   </cfif> 

   <cfreturn resultset>
</cffunction>

Таким образом, вы нажимаете JSON на API подписки, который преобразует данные в структуру и гарантирует, что у вас есть все нужные данные, и передает их службе подписки. Метод createSubscription в службе подписки проверяет, существует ли listid, и проверяет, подписан ли уже человек. Если список верный, а подписка не существует, вставьте новую подписку в базу данных, в противном случае возвращайте результаты, указывающие на ошибки в структуре, на уровень API, который преобразует его в JSON и возвращает его.

Преимущество этого состоит в том, что вы можете повторно использовать службы в своем приложении, не проходя через уровень API, а ваш уровень API обрабатывает запросы на правильные методы обслуживания и следит за тем, чтобы для них были доступны соответствующие данные. ,

Не передавайте локальную область вокруг! Там может быть множество вещей, включая все другие методы в сервисе. Просто верните то, что требуется, и ничего больше.

Есть и другие способы решения этой проблемы, которые могут быть более точными - например, вы можете фактически поместить аргументы в вызов метода метода для CFC из JSON. Вы можете использовать cfajaxproxy, чтобы создать слой между вашим сервисом и вашим javascript, позволяя вам вызывать ваши методы cfc непосредственно как функции javascript. И я уверен, что есть и другие решения.

Помните .... ColdFusion == Серверная часть, Javascript == Клиентская сторона. Разделите их. Поместите слой между ними для обработки сообщений.

Надеюсь, это поможет.

2 голосов
/ 29 февраля 2012

Если вы хотите, чтобы метод использовал строку struct или json в качестве одного аргумента, вы можете сделать что-то вроде ...

<cffunction name="myFunction" access="remote" returntype="Struct" returnformat="JSON">
    <cfargument name="data" type="any" required="true">

    <cfif isJson(arguments.data)>
        <cfset arguments.data = deserializeJSON(arguments.data) />
    </cfif>

    <cfif NOT isStruct(arguments.data)>
        <cfthrow message="argument must be structure or a json string" />
    </cfif>

    ... 

</cffunction>
1 голос
/ 29 февраля 2012

Отредактировано из исходного решения:

Не похоже, что вы можете напрямую передать объект JSON в Coldfusion и интерпретировать его как Struct.Что вы МОЖЕТЕ сделать, так это создать метод-оболочку вокруг существующего метода, который принимает строку JSON, а затем десериализует ее в структуру в Coldfusion, чтобы передать ее существующему методу:

<script>
    var data = { dude: "wow"};
    $(function() {
        $('#ajax').click(function() {
            $.getJSON(
                "test.cfc", 
                {
                    method: "foo",
                    json: JSON.stringify(data)
                },
                function(data) {
                    // so something with result
                }   
            );
        });
    })
</script>

И Coldfusion:

<cffunction name="foo" access="remote" returntype="Struct" returnformat="JSON">
    <cfargument name="json" type="string" />

        <cfset myStruct = DeserializeJSON(arguments.json) />

        <!--- now call your existing method passing it myStruct --->
</cffunction>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...