2012-02-28 11 views
6

Ho un CFC esistente che funziona correttamente quando si passano strutture nel metodo.Come passare STRUCT - OR - JSON al metodo CFC Coldfusion

Il problema è che ora dobbiamo anche trasferire i dati nella stessa funzione tramite JSON.

Ecco il frammento di 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 /> 

Ecco come si passa nella struttura:

<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> 

Ora, abbiamo anche bisogno di passare nel seguente, ma sono ovviamente ottenere errori dovuti al CFC in attesa di una struttura:

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 
); 

}

Come possiamo passare con successo nello snippet getJSON?

Grazie.

risposta

3

JSON è solo una stringa, quindi è necessario "gestire" la chiamata al metodo prima che raggiunga il livello di servizio effettivo.

Danimal ha ragione nel senso che ciò che devi fare è creare un wrapper del servizio Web a livello del tuo servizio.

Così il vostro metodo di servizio assomiglia a questo:

<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> 

tuo API abbonamento è simile al seguente:

<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> 

in modo da spingere il JSON alla API di sottoscrivere, che converte i dati in una struct e ti assicura di avere tutti i dati giusti disponibili e li passa al tuo servizio di abbonamento. Il metodo createSubscription nel servizio di sottoscrizione verifica se esiste il listid e controlla se la persona è già iscritta. Se l'elenco è valido e la sottoscrizione non esiste, inserire la nuova sottoscrizione nel database, altrimenti restituire risultati che indicano cosa è andato storto in una struttura del livello API, che lo converte in JSON e lo restituisce.

Il vantaggio di questo è che è possibile riutilizzare i servizi nell'applicazione senza dover passare attraverso il livello API e il livello api gestisce l'invio delle richieste ai metodi di servizio corretti e assicurandosi che siano disponibili dati appropriati per loro.

Non passare l'ambito locale in giro!Ci può essere un carico di cose, inclusi tutti gli altri metodi nel servizio. Basta restituire ciò che è richiesto e nient'altro.

Esistono altri modi per risolvere ciò che potrebbe essere più ordinato: ad esempio, è possibile inserire argomenti in una chiamata al metodo metodo su un CFC di JSON. Puoi usare cfajaxproxy per creare il livello tra il tuo servizio e il tuo javascript, permettendoti di chiamare i tuoi metodi cfc direttamente come funzioni javascript. E sono sicuro che ci sono altre soluzioni in cima a questi.

Ricordare .... ColdFusion == Serverside, Javascript == clientide. Separali. Metti uno strato tra di loro per gestire le comunicazioni.

Spero che questo aiuti.

+0

Non sto ospitando il servizio API. Solo effettuando una chiamata a un'API remota. –

+0

Se utilizzo questo metodo, vedo che hai modificato il cfargument in una stringa di testo. Questo non spezzerà la mia altra chiamata che passa in una struttura? –

+0

Sì, ma non dovresti chiamare il livello API dall'interno dell'applicazione. Dovresti chiamare direttamente il livello di servizio e il metodo createSubscription. Questo metodo ti consente di passare una struttura come una raccolta di argomenti. –

1

cura da soluzione originale:

Non sembra come è possibile passare un oggetto JSON direttamente a Coldfusion e lo hanno interpretato come una struct. Che cosa si può fare è quello di creare un metodo involucro intorno al metodo esistente che accetta una stringa JSON, quindi deserializza ad una struct in Coldfusion di passare al tuo metodo esistente:

<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> 

E il 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> 
+0

Purtroppo, questo non funziona. Grazie per la tua risposta però. –

+0

Vedere la mia soluzione modificata. –

+0

Grazie. Ci proverò. –

2

Se si desidera un metodo per prendere o una struttura o una stringa JSON come un unico argomento, si può fare qualcosa di simile ...

<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> 
Problemi correlati