Проблемы с функциональностью метода OnCFCRequest в моем понимании - PullRequest
1 голос
/ 12 апреля 2019

Этот пример не работает должным образом, когда я передаю аргумент filters в отдельную функцию, чтобы использовать его для поиска

, например,

неверный вызов функции Search, 4-йАргумент (фильтры) имеет недопустимый тип, не может приводить String [{"groupOp": "AND", "rules": [{"field": "errorid", "op": "eq", "data":"1"}, {"field": "line", "op": "eq", "data": ...] до значения типа [struct]

Я называю этовот так:

#SearchOptions(arguments.filters)#

из функции

<cfset filters = {"groupOp":"AND","rules":[{"field":"template","op":"eq","data":"a"},{"field":"error_type","op":"eq","data":""}]}>

<cfdump var="#filters#">
<cfoutput>
    <cfloop from="1" to="#arrayLen(filters.rules)#" index="i">
        #i#
        <cfset dataArr = filters.rules[i]>
        <cfloop collection="#dataArr#" item="key">
            #key#   
        </cfloop>
    </cfloop>   
</cfoutput>

В моем приложении была функция onCFCRequest

<cffunction name="onCFCRequest" access="public" returntype="void" output="true" hint="I process the user's CFC request.">
    <cfargument name="component" type="string" required="true" hint="I am the component requested by the user." />
    <cfargument name="methodName" type="string" required="true" hint="I am the method requested by the user." />
    <cfargument name="methodArguments" type="struct" required="true" hint="I am the argument collection sent by the user." />
    <cfif !structKeyExists( application.apiCache, arguments.component )>
        <cfset application.apiCache[ arguments.component ] = createObject( "component", arguments.component ).init() />
    </cfif>
    <cfset local.cfc = application.apiCache[ arguments.component ] />
    <cfinvoke returnvariable="local.result" component="#local.cfc#" method="#arguments.methodName#" argumentcollection="#arguments.methodArguments#" />
    <cfset local.responseData = "" />
    <cfset local.responseMimeType = "text/plain" />
    <cfif structKeyExists( local, "result" )>
        <cfparam name="url.returnFormat" type="string" default="#getMetaData( local.cfc[ arguments.methodName ] ).returnFormat#" />
        <cfif ( (url.returnFormat eq "json") && !structKeyExists( url, "callback" ) )>
            <cfset local.responseData = serializeJSON( local.result ) />
            <cfset local.responseMimeType = "text/x-json" />
        <cfelseif ( (url.returnFormat eq "json") && structKeyExists( url, "callback" ) )>
            <cfset local.responseData = ( "#url.callback#(" & serializeJSON( local.result ) & ");" ) />
            <cfset local.responseMimeType = "text/javascript" />
        <cfelseif (url.returnFormat eq "wddx")>
            <cfwddx action="cfml2wddx" input="#local.result#" output="local.responseData" />
            <cfset local.responseMimeType = "text/xml" />
        <cfelse>
            <cfset local.responseData = local.result />
            <cfset local.responseMimeType = "text/plain" />
        </cfif>
    </cfif>
    <cfset local.binaryResponse = toBinary( toBase64( local.responseData ) ) />
    <cfheader name="content-length" value="#arrayLen( local.binaryResponse )#" />
    <cfcontent type="#local.responseMimeType#" variable="#local.binaryResponse#" />
</cffunction>

1 Ответ

3 голосов
/ 12 апреля 2019

Я узнаю этот шаблон из блога Бена Наделя . В коде, который вы публикуете в своем вопросе, отсутствуют две важные части. Во-первых, метод, который вызывается cfinvoke из вашего объекта application.apiCache - вызов этого метода завершается неудачно, и генерируется исключение. И, во-вторых, код JavaScript, который вызывает этот метод.

Ошибка, на самом деле, имеет простую причину. Ваш код JavaScript, скорее всего, передает данные в виде строки, когда вы передаете объект JavaScript. Либо потому, что вы вызываете JSON.stringify, либо потому, что какая-то «магия» используемой вами библиотеки сериализует объект в строку.

Решение состоит в том, чтобы вызвать DeserializeJSON для четвертого аргумента (именуемые фильтры в соответствии с сообщением об ошибке) вашей функции ColdFusion. Я сам использую код, подобный следующему. bSave становится true только если аргумент может быть успешно преобразован в структуру.

Если в функции есть теги cfargument, вы должны изменить атрибут type рассматриваемого элемента на string, соответственно.

<cfset local.struVals = {}>
<cfset local.bSave = false>

<cftry>
  <cfset local.struVals = DeserializeJSON( Arguments.filters )>

  <cfset local.bSave = true>

  <cfcatch></cfcatch>
</cftry>

<cfif local.bSave>

</cfif>

...