ajax发送put请求参数,请求参数和PUT方法(Request params and PUT method)

请求参数和PUT方法(Request params and PUT method)

我试图通过基于Grails的应用程序获取PUT请求传递的请求参数。

我正在使用以下客户端代码发出请求:

$.ajax({

url: 'api/controllerName/anId',

type: 'PUT',

data: $('form').serialize()

})

与以下映射:

"/api/$controller/$id?" {

action = [ GET: "read", POST: "create", PUT: "update", DELETE: "delete"]

}

但我的控制器的操作收到空的参数列表,只有id值。 我试图把它的内容放在日志中,只看到:

[id:anId, action:[GET:read, POST:create, PUT:update, DELETE:delete], controller:controllerName]

request.getParameterNames()返回值的空值列表。

正如我从FireBug看到的,请求包含这个参数,并且将Content-Type设置为application/x-www-form-urlencoded; charset=UTF-8 application/x-www-form-urlencoded; charset=UTF-8

如果我使用GET / POST方法 - 一切都按预期工作,我可以获取所有传递的参数。

我如何获得传递的参数?

更新 :我刚才发现PUT意味着将数据作为JSON / XML传递给body。 顺便说一句,这个问题仍然是实际的,以防万一

I'm trying to get request params passed by PUT request, at Grails-based app.

I'm using following client code to make request:

$.ajax({

url: 'api/controllerName/anId',

type: 'PUT',

data: $('form').serialize()

})

with following mapping:

"/api/$controller/$id?" {

action = [ GET: "read", POST: "create", PUT: "update", DELETE: "delete"]

}

But my controller's action receives empty params list, with only id value. I tried to put it content to logs and saw only:

[id:anId, action:[GET:read, POST:create, PUT:update, DELETE:delete], controller:controllerName]

and request.getParameterNames() returns empty list of values.

As I see from FireBug, request contains this params, and have Content-Type as application/x-www-form-urlencoded; charset=UTF-8

If I'm using GET/POST method - everything is working as expected, I can get all passed parameters.

How I can get access to passed parameters?

Update: I've just figured that PUT implies passing data as JSON/XML in body. Btw, this question is still actual, just in case

原文:https://stackoverflow.com/questions/7195872

更新时间:2019-11-04 14:25

最满意答案

我今天有完全相同的问题,并能够解决它。 我使用JQuery向Grails RESTful WebService(方法:“PUT”)做了一个ajax请求,但参数映射是空的。

只是想在这里分享我的解决方案。

我必须JSON.stringify我的数据,并将contentType设置为“application / json”,然后在我的Grails控制器中使用request.JSON(如前所述)。

示例(JQuery Ajax请求):

$.ajax({

url: "/entries/" + id,

contentType: "application/json",

type: "PUT",

dataType: "json",

data: JSON.stringify({'name' : name, 'date': date}),

success: function(msg) {

console.log('updated...')

$.mobile.changePage($('#list'));

}

之后我可以使用:

request.JSON

在我的控制器中,以获取由ajax请求发送的数据(参数仍为空)。 如果我没有使用JSON.stringify并设置内容类型,我有以下Grails错误:

Error 2012-04-03 13:50:20,046 [http-bio-8080-exec-3] ERROR errors.GrailsExceptionResolver - IllegalStateException occurred when processing request: [PUT] /entries/2

getReader() has already been called for this request. Stacktrace follows:

Message: getReader() has already been called for this request

我使用Grails 2.0.1和JQuery 1.7.1

I had the exact same issue today and was able to fix it. I did an ajax request with JQuery to a Grails RESTful WebService (method: "PUT"), but the parameter map was empty.

Just want to share my solution here.

I had to JSON.stringify my data and set the contentType to "application/json" and then use request.JSON (as suggested before) in my Grails controller.

example (JQuery Ajax Request):

$.ajax({

url: "/entries/" + id,

contentType: "application/json",

type: "PUT",

dataType: "json",

data: JSON.stringify({'name' : name, 'date': date}),

success: function(msg) {

console.log('updated...')

$.mobile.changePage($('#list'));

}

afterwards I could use:

request.JSON

in my Controller in order to get the data sent by the ajax request (params was still empty). If I did not use JSON.stringify and set the content type, I had the following Grails error:

Error 2012-04-03 13:50:20,046 [http-bio-8080-exec-3] ERROR errors.GrailsExceptionResolver - IllegalStateException occurred when processing request: [PUT] /entries/2

getReader() has already been called for this request. Stacktrace follows:

Message: getReader() has already been called for this request

I'm using Grails 2.0.1 and JQuery 1.7.1

相关问答

我今天有完全相同的问题,并能够解决它。 我使用JQuery向Grails RESTful WebService(方法:“PUT”)做了一个ajax请求,但参数映射是空的。 只是想在这里分享我的解决方案。 我必须JSON.stringify我的数据,并将contentType设置为“application / json”,然后在我的Grails控制器中使用request.JSON(如前所述)。 示例(JQuery Ajax请求): $.ajax({

url: "/entries/"

...

在这种情况下,不要使用RKRoute 。 当你调用put...时,明确地提供适当的路径。 请注意,您还应该有2个响应描述符,因为路径模式不同。 Just don't use the RKRoute in this case. Explicitly supply the appropriate path when you call put.... Note that you should also have 2 response descriptors because the path patter

...

最后我找到了这个解决方案:在Zend / Controller / Plugin /中你可以找到PutHandler.php。 它可以用于使用$ this-> getRequest() - > param_name来获取PUT参数。 将它包含在你的boostrap.php文件中: protected function _initRestRoute()

{

$this->bootstrap('frontController');

$frontController = Zend_Con

...

我假设你要问的是,如果你可以有这样的方法: def restaction(request, id):

if request.method == "PUT":

someparam = request.PUT["somekey"]

答案是否定的,你不能。 Django不会为PUT,OPTIONS和DELETE请求构建这样的字典, 这里介绍的推理。 为了总结一下,REST的概念是,您交换的数据可能比简单的键映射到值更复杂。 例如,打印图像,或使用json。 一个框架不知道你可能

...

您可以在路由中传递id ,而有效负载中的Actor使用following overload作为第二个参数作为对象: HttpResponseMessage response = client.PutAsJsonAsync("api/Actors/123", new

{

actor = new Actor

{

Name = "John Smith",

Age = 30,

}

});

You could pass the id in the

...

调用资源时,您可以像这样指定urlParams和formBody Params resource(auth).putRequest({id: data.id}, {thing1: new, thing2: old}).$promise

第一个参数是urlParams,第二个是formBody,有关详细信息,请查看文档 When calling a resource you can specify the urlParams and the formBody Params like so reso

...

作为解决方法,我在request.body中找到它们并手动解析编码参数。 这有点烦人,但它确实有效。

new_values = urlparse.parse_qs(self.request.body)

# values show as lists with only one item

for k in new_values:

new_values[k] = new_values[k][0]

As a

...

你说过,你的logcat中出现“ArrayIndexOutOfBound”错误。 可能是你的getParams()方法有问题。 更改for循环: for (int i = 0; i <= tripData.length; i++)

至: for (int i = 0; i < tripData.length; i++)

立即检查,如果您遇到任何其他问题,请在此处显示您的logcat。 You said, getting "ArrayIndexOutOfBound" error in your

...

只做一次改变,它将完美无缺。 params.put("countryid", ""+countryID);

Do only one change, it will work perfect. params.put("countryid", ""+countryID);

我建议将ReorderedTasks [i] .ID.ToString()直接放到url路径。 var request = new RestRequest($"api/task/5/{ReorderedTasks[i].ID.ToString()}/", Method.PUT);

它将有助于减少http请求格式可能出现的问题。 I suggest to put ReorderedTasks[i].ID.ToString() directly to url path. var request =

...

<think>好的,我现在要帮助用户解决关于Layui中使用Promise封装请求并处理data参数的问题。首先,我需要回顾之前的对话历史,看看用户之前问了什么,然后理解当前的问题。 用户之前询问了如何配置请求根地址,我给出了几种方案,包括全局配置、环境自适应、创建请求实例等。现在用户的问题是希望用Promise封装Layui的请求,并处理data参数的问题。我需要确定用户的具体需求是什么,可能他们遇到了参数处理上的困难,比如格式转换或者不同请求方法下的参数传递问题。 首先,我需要回忆Layui的请求方式。Layui的$.ajax是基于jQuery的,但可能有自己的封装。通常,在Layui中,使用layui.use('jquery', function(){ ... })来引入jQuery,然后使用$.ajax。不过,原生的Layui可能使用自己的模块,所以可能需要确认一下。 用户提到Promise封装,这意味着他们希望将异步请求转换为Promise对象,以便使用async/await或者.then()链式调用,避免回调地狱。同时,处理data参数可能涉及到如何统一处理请求参数,比如根据请求方法(GET、POST)自动处理参数的位置,例如GET请求参数放在URL查询字符串,POST放在请求体。 接下来,我需要考虑如何将Layui的ajax请求封装成Promise。通常,可以通过返回一个new Promise对象,在成功回调中resolve,失败时reject。同时,处理data参数可能需要在封装函数中根据请求方法自动处理参数的位置,或者统一处理数据格式,比如将对象转换为JSON字符串,设置正确的Content-Type头。 另外,用户可能在之前的配置根地址的基础上,希望这个封装也能集成baseURL,所以可能需要结合之前的配置方案,比如全局的apiConfig.baseURL,或者使用环境变量。 还需要考虑错误处理,比如网络错误、服务器返回的非200状态码,以及业务逻辑错误(如后端自定义的错误码)。在Promise封装中,需要区分这些错误类型,并统一抛出,让调用者能够捕获处理。 关于data参数的问题,常见的问题有:POST请求需要将data作为请求发送,而GET请求需要将参数拼接到URL上。在封装时,需要根据请求方法自动处理,比如如果是GET,将data转换为查询字符串附加到URL后;如果是POST,将data作为请求体,并设置正确的Content-Type。此外,可能需要处理data为表单数据、JSON、或者文件上传的情况,但用户可能指的是普通的JSON数据。 另外,用户可能希望data参数可以灵活处理,比如在某些情况下需要转换数据格式,或者处理嵌套对象,或者过滤掉空值等。因此,在封装函数中,可以添加预处理data的逻辑,比如使用qs库序列化参数,或者手动处理。 最后,需要给出示例代码,说明如何调用封装后的请求函数,处理成功失败的情况,并展示如何处理data参数的不同情况。 现在,我需要整理这些思路,分步骤解释如何用Promise封装Layui的请求,并处理data参数的问题。需要确保代码示例正确,并且覆盖常见的用例,比如GETPOST请求,处理不同的data参数类型,错误处理等。同时,结合之前提到的baseURL配置,提供一个完整的解决方案。</think>以下是针对 Layui 的 Promise 请求封装方案,包含 **统一错误处理** **智能 `data` 参数处理** 的核心实现: --- ### 一、基础封装方案 #### 1. 核心封装函数 ```javascript // 创建 Promise 封装的请求函数 function layuiRequest(options = {}) { return new Promise((resolve, reject) => { // 合并全局配置(如之前配置的 baseURL) const mergedOptions = { ...{ method: 'GET', headers: { 'Content-Type': 'application/json' } }, ...options } // 智能处理 data 参数 if (mergedOptions.data) { if (mergedOptions.method.toUpperCase() === 'GET') { // GET 请求自动转换为 URL 参数 mergedOptions.url += '?' + new URLSearchParams(mergedOptions.data).toString() delete mergedOptions.data // 移除 GET 请求的 data 属性 } else { // 非 GET 请求自动 JSON 序列化 mergedOptions.data = JSON.stringify(mergedOptions.data) } } // 执行 Layui 原生请求 layui.$.ajax({ ...mergedOptions, success: (res) => { // 业务状态码拦截(示例代码,需根据实际 API 结构调整) if (res.code !== 200) { return reject(new Error(res.message || '业务逻辑错误')) } resolve(res.data) }, error: (xhr, status, error) => { // 统一错误处理 reject(new Error(`请求失败: ${status} | ${error}`)) } }) }) } ``` --- ### 二、核心功能解析 #### 1. 智能 `data` 处理逻辑 | 请求方法 | 处理方式 | 示例转换 | |-----------|-----------------------------------|-----------------------------------| | **GET** | 自动转换为 URL 查询参数 | `{id:1}` → `?id=1` | | **POST** | 自动序列化为 JSON 字符串 | `{name:"John"}` → `"{"name":"John"}"` | | **PUT** | 同 POST 处理 | | #### 2. 错误处理层级 ```javascript try { const data = await layuiRequest({ /*...*/ }) } catch (err) { // 捕获以下三种错误类型: // 1. 网络错误(xhr.status=0) // 2. HTTP 状态码错误(4xx/5xx) // 3. 自定义业务逻辑错误(res.code!=200) } ``` --- ### 三、进阶用法 #### 1. 文件上传特殊处理 ```javascript // 创建 FormData 实例 const formData = new FormData() formData.append('file', file) // 调用请求(自动关闭 JSON 序列化) layuiRequest({ method: 'POST', headers: { 'Content-Type': 'multipart/form-data' }, // 必须手动设置 data: formData }) ``` #### 2. 自定义数据处理 ```javascript // 在封装函数中添加预处理钩子 function layuiRequest(options) { // 前置处理(示例:过滤空值) if (options.dataFilter) { options.data = options.dataFilter(options.data) } // ...原有逻辑... } // 使用示例 layuiRequest({ data: { name: 'John', age: null }, dataFilter: (data) => { return Object.fromEntries( Object.entries(data).filter(([_, v]) => v !== null) ) } }) ``` --- ### 四、最佳实践建议 #### 1. 类型安全校验(推荐搭配 TypeScript) ```typescript interface RequestOptions<T = any> { url: string method?: 'GET' | 'POST' | 'PUT' | 'DELETE' data?: T headers?: Record<string, string> } function layuiRequest<T>(options: RequestOptions): Promise<T> { // 实现逻辑... } ``` #### 2. 性能优化方案 ```javascript // 添加请求缓存机制 const requestCache = new Map() function cachedRequest(options) { const cacheKey = JSON.stringify(options) if (requestCache.has(cacheKey)) { return requestCache.get(cacheKey) } const promise = layuiRequest(options).finally(() => { requestCache.delete(cacheKey) }) requestCache.set(cacheKey, promise) return promise } ``` --- ### 五、完整调用示例 ```javascript // GET 请求示例 layuiRequest({ url: '/api/user', params: { id: 123 } // 自动转换为 ?id=123 }) .then(data => console.log('用户数据:', data)) .catch(err => console.error('请求失败:', err)) // POST 请求示例 layuiRequest({ method: 'POST', url: '/api/create', data: { name: 'Alice', age: 28 } // 自动序列化为 JSON }) ``` 这种封装方案可以实现: 1. **参数智能化处理** - 自动区分 GET/POST 参数格式 2. **错误统一拦截** - 网络层与业务层错误分类处理 3. **类型安全** - 通过 TypeScript 增强代码可靠性 4. **灵活扩展** - 支持文件上传、缓存等高级场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值