【问题标题】:Return CFC Query Data from AJAX call从 AJAX 调用返回 CFC 查询数据
【发布时间】:2015-03-08 22:53:32
【问题描述】:

我正在对 CFC 进行 AJAX 调用以从我的数据库中返回一条记录。记录始终以字符串形式返回。然后我用该值更新一个输入字段。

问题是我的字段正在填充以下内容:

<wddxPacket version='1.0'><header/><data><string>0</string></data</wddxPacket>

相反,我只想要字符串的值。在这个例子中:0

AJAX 调用:

<script>
function populateSalesTax(){
    // Populate the start and stop odometer text boxes
    // when the selectlist ajax completes successfully

        $.ajax({
            url:'cfcs/taxdata.cfc?method=getSalesTax',
            data: { company_name: $("##company_name>option:selected").attr("Value") },
            success: function(response) {
                console.log('Sales Tax Fubction Ran Successfully');
                $("##taxRate").val( response );

                },
            error: function(response) {
                console.log('Error' + response)}
          });
    }
</script>

CFC功能:

<cffunction name="getSalesTax" access="remote" returnType="string">
   <cfargument name="company_name" type="any" required="true">

   <!--- localize function variables --->
   <cfset var taxDetail = "">
   <cfoutput>
   <cfquery name="taxDetail" datasource="#datasource#">
       SELECT tax_rate
       FROM   customer_table
       <!--- adjust cfsqltype if needed --->
       WHERE company_name = <cfqueryparam value="#ARGUMENTS.company_name#"
                                cfsqltype="cf_sql_varchar">
   </cfquery>
   </cfoutput>

   <cfreturn taxDetail.tax_rate>
</cffunction>

输入字段:

<cfinput name="taxRate" id="taxRate" type="text" size="2" readonly="yes">

【问题讨论】:

  • 在你的 AJAX 调用中,尝试cfcs/taxdata.cfc?method=getSalesTax&amp;ReturnFormat=json
  • 那行得通。谢谢。
  • 最简单的方法是根本不使用 ajax。在 .cfm 文件中运行该函数并使用 cfinput 标记的 value 属性。与您的问题无关,但您的函数中不需要 cfoutput 标签。 cfquery 有一个内置的。
  • 您为什么建议最简单的方法是不使用 AJAX?
  • 如果存在上述功能,您不使用 AJAX 的建议会导致它停止工作。

标签: jquery ajax coldfusion cfc


【解决方案1】:

我在这里有很多代码,因为我做的事情与大多数人不同,但这是一种演变。 以下是我创建典型表的方法:

if exists (select * from sysobjects where id = object_id(N'myTable') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
DROP TABLE myTable
GO
CREATE TABLE myTable(
myTableID Int Identity(1000,1) PRIMARY KEY NONCLUSTERED
,myTableName varchar(128) default ''
,myTableDesc varchar(max) default ''
,myTableSort Int default 0
)
GO
INSERT INTO myTable(myTableName,myTableSort) VALUES('One',1)
INSERT INTO myTable(myTableName,myTableSort) VALUES('Two',2)
INSERT INTO myTable(myTableName,myTableSort) VALUES('Three',3)

我使用存储过程。下面是 SQL 代码:

create schema myTable authorization dbo
-- It might seem odd to create a schema called with the name of the table, but that's how I organize the stored procedures by table name.
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'myTable.[get]') AND type in (N'P', N'PC'))
DROP PROC myTable.[get]
GO
CREATE PROC myTable.[get]
(@UsrID Int
,@RemoteAddr Varchar(15)
,@myTableID Int
) AS
SELECT myTableID,myTableName,myTableDesc,myTableSort
FROM myTable
WHERE myTableID = @myTableID
GO
exec myTable.[get] 0,'',1001

@UsrID 是每个存储过程中的第一个参数。谁想知道。

@RemoteAddr 是每个存储过程中的第二个参数。这是用户的IP地址。 现在,我知道这不是万无一失的,但认为这里的安全性是这样的 1) @UsrID 是他们知道的(他们必须知道密码才能以用户身份登录)。

2) @RemoteAddr 是他们拥有的东西(尽管 IP 地址可以被欺骗)。

@myTableID 是@myTable 的主键。我总是将主键命名为表名,后跟 ID。

这是一个典型的 .cfm 页面:

<cfscript>

</cfscript>

<cfoutput>
<cfinclude template="/Inc/html.cfm">
<link rel="stylesheet" type="text/css" href="Index.css">
<cfinclude template="/Inc/body.cfm">
<ul>
    <li><a class="myClass" data-mytableid="1000" href="JavaScript:;">Click One!</a></li>
    <li><a class="myClass" data-mytableid="1001" href="JavaScript:;">Click Two!</a></li>
    <li><a class="myClass" data-mytableid="1002" href="JavaScript:;">Click Three!</a></li>
</ul>
<cfinclude template="/Inc/foot.cfm">
<script src="Index.js"></script>
<cfinclude template="/Inc/End.cfm">
</cfoutput>

我在所有页面中都包含的脚本:

window.dom = {}
dom.msg = $('#msg')
dom.main = $('main')
dom.fail = function(xhr, status, response) {
    dom.msg.text(status + ': ' + response).addClass('label-warning')
    dom.main.html(xhr.responseText)
    debugger
}

页面本身的脚本:

(function() {
    $(document).on('click','.myClass',clicked)

    function clicked() {
        var local = {}
        local.url = 'myTable.cfc'
        local.type = 'POST' // or GET
        local.dataType = 'json'
        local.data = {}
        local.data.method = 'get';
        local.data.myTableID = $(this).data('mytableid')
        local.context = this;
        result = $.ajax(local)
        result.fail(dom.fail)
        result.done(done)
    }
    function done(response, status, xhr) {
//      console.log(response.COLUMNS)
//      console.log(response.DATA)
//      console.log(response.DATA[0])
//      console.log(response.DATA[0][0]) // myTableID
//      console.log(response.DATA[0][1]) // myTableName
//      console.log(response.DATA[0][2]) // myTableDesc
//      console.log(response.DATA[0][3]) // myTableSort
//      console.log(status)
//      console.log(xhr)
    }
})()

最后,myTable.cfc:

component {

remote function get(myTableID) returnformat='json' {
    storedproc dataSource=session.dataSource
        procedure='myTable.[get]' {
        procparam cfSqlType='cf_sql_integer' value=session.Usr.UsrID;
        procparam cfSqlType='cf_sql_varchar' value=session.RemoteAddr;
        procparam cfSqlType='cf_sql_integer' value=arguments.myTableID;
        procresult resultset=1 name='result';
    }
    return result
}
}

我应该粘贴一个缩写的 Application.cfc:

component {
this.Name = 'myAJAX'
this.dataSource = 'LR2015Summer1'
this.SessionManagement = true

function onSessionStart() {
    session.dataSource = this.dataSource
    session.RemoteAddr = getPageContext().getRequest().getRemoteAddr()
    session.Usr = {}
    session.Usr.UsrID = 0
}

function onRequestStart(LogCFCName) {
    setting showDebugOutput=false;
    if (isDefined('url.onSessionStart')) {
        onSessionStart()
    }
    request.msg = ''
    request.mod = 'label-info'

    request.title='How I AJAX and return a query'
    request.home = '/HowIWrite/AJAX/cfc'
    request.css       = url.css       ?: true
    request.js        = url.js        ?: true
    request.bootstrap = url.bootstrap ?: true
    request.bootstrap_theme = 'bootstrap-theme'
    request.tryCatch  = url.tryCatch  ?: false
    request.navbar    = url.navbar    ?: true
    request.container = url.container ?: true
    request.GoogleMaterialdesign = url.GoogleMaterialdesign ?: true
    request.jQueryUI  = url.jQueryUI  ?: false
    request.jQueryUI_theme = 'ui-lightness' // black-tie,blitzer,cupertino,dark-hive,dot-luv,eggplant,excite-bike,flick,hot-sneaks,humanity,le-frog,mint-choc,overcast,pepper-grinder,redmond,smoothness,south-street,start,sunny,swanky-purse,trontastic,ui-darkness,ui-lightness,vader

    request.cgiName = getPageContext().getRequest().getServletPath()
    request.cgiName = Left(request.cgiName,Len(request.cgiName)-4)
    request.cgiName = ListLast(request.cgiName,'/')
    request.cssName = request.cgiName & '.css'
    request.jsName  = request.cgiName & '.js'
}

}

【讨论】:

    【解决方案2】:

    您可以这样修改您的 CFC:

    <cfset response = { taxRate = taxDetail.tax_rate } />
    <cfreturn serializeJSON(response)>
    

    (ajax成功方法应该有response.TAXRATE)

    或您的 ajax 调用网址:

    cfcs/taxdata.cfc?method=getSalesTax&amp;ReturnFormat=json

    但是

    从您在 ajax 请求 url:'cfcs/taxdata.cfc?method=getSalesTax' 中的相对路径来看,我可以放心地假设您正在尝试在同一来源(同一站点)上执行 ajax 请求,而您实际上并不需要 remote 方法,但 publicpackage 方法。

    您应该意识到声明方法remote 带来的安全问题。如果没有适当的安全层或role 定义,您已经打开了该方法供任何人使用,包括恶意用户。

    所以你应该拥有的是:

    • CFC 前面的另一个抽象层 - 至少只是一个实例化对象并调用 getSalesTax 的 cfm,但理想情况下是一个框架
    • publicpackage 的访问权限,而不是 remote
    • 在返回税率响应对象的抽象层上声明的适当内容类型(例如&lt;cfcontent type="application/json" reset="true" /&gt;

    【讨论】:

    • 我没有做过很多 ajax 调用,最近也没有,但我对问题的记忆模糊不清,除非方法是远程的。
    • ajax 请求与任何其他请求一样,除了它是异步 或不按顺序。在现代浏览器中,禁止 ajax 请求在与当前域不同的域(源)上运行脚本调用,除非在 allow-origin-access 标头中以不同方式提供(查找 CORS)。这是出于安全原因而实施的,涉及跨站点脚本、受感染的 Web 应用程序等。在这种情况下我并不是说这是一个问题,而是我建议他关闭他的潜在安全漏洞app,也就是远程方法
    • 我已经开始在数据的来源和数据的使用位置之间使用一个层。称它为 AppApi 或类似的东西。 AppApi 有一个类(可能是 AppObj)被实例化,所以 AppApi 有远程方法来调用 AppObj 上的公共方法。我看到以这种方式做事的主要好处是 AppObj 对象在 AppApi 中是持久的,但我认为 AppApi 中页面调用的方法需要是远程的,而不是公共的或包的。我对你说的话感到困惑吗?
    • 谁在使用这个 api?它只是您的网络应用程序还是用于 3rd 方应用程序?您的 api 是否需要任何形式的身份验证?我问这个的原因是确定你是否真的需要远程方法。 Access remote 创建远程应用或第三方应用可以使用的 Web 服务。
    • 如果不是这种情况,那么您不需要远程方法,但这里有一个您需要的简单示例:myapp.com/index.cfm?action=getTaxIndex.cfm 这里有一个决策块 if(action==getTax),如果是这样,它会实例化 AppApi.AppObject 并调用 myTax = AppObject.getSalesTax()。然后要返回 json,您只需添加 &lt;cfcontent type="application/json" reset="true" /&gt;&lt;cfoutput&gt;#serializeJSON(myTax)#&lt;/cfoutput&gt;。这里的getSalesTax 方法不需要 需要是远程的,而是公开的。这是一种粗略的 MVC 方法。我建议研究像 FW1 这样的冷融合 mvc 框架。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 2014-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多