在 ASP.NET 和 C# 中手动进行 AJAX 调用
Posted
技术标签:
【中文标题】在 ASP.NET 和 C# 中手动进行 AJAX 调用【英文标题】:Manually making AJAX calls in ASP.NET and C# 【发布时间】:2011-01-17 11:00:58 【问题描述】:我想在 ASP.NET 中编写自己的 AJAX,而不是使用 ASP.NET ScriptManager 等。
为什么?我喜欢手动做一些事情,并且知道事情是如何从内部工作的,所以我只想为自己做这件事。
所以我的问题是,在我进行 AJAX 调用之后:
var ajaxCall = new XMLHttpRequest();
....
ajaxCall.send(null)
我如何在 C# 中添加(或不添加)Page_Load,以便它侦听并返回一个字符串。
【问题讨论】:
【参考方案1】:+1 为你自己做事 - 我想知道在使用为我做事的框架之前我可以自己做事,所以如果它成功了,我大致知道如何开始修复它。
无论如何,你的问题。只需使用 ASP.NET 或 Response.Write 正常输出数据。如果您正在执行 POST 请求,您可以使用 if (Page.IsPostBack) 在 Page_Load 中检查这一点。请记住,通常您只会发送部分页面的数据,而不是整个页面本身,所以您不需要<html>
、<head>
或<body>
标签。
当我之前在 ASP.NET 网站上看到过这种情况时,AJAX 调用使用了单独的页面(例如 index.aspx = 普通站点,index-ajax.aspx = ajaxified 页面组件。)
if (Page.IsPostBack)
Response.Write("Hello, world! From AJAX.");
您不必使用 Page.IsPostBack,大多数 AJAX 请求只是 GET,所以如果您放入 Page_Load:
Response.Write("Hello, world! From AJAX.");
然后对该页面执行 AJAX 调用,您将收到“Hello, world! From AJAX”。从 AJAX 调用返回。
【讨论】:
这很好用。非常感谢。我创建了一个单独的页面,它准确地返回了我正在寻找的内容。非常感谢。尽管从我从其他答案中读到的内容来看,这看起来是一种效率低下的方法。非常感谢! 是的,理想情况下你会在 ASP 标记等中创建你的页面,这只是一个简单的例子。也正如其他人所说,ASP.NET AJAX 处理非常体面而且非常简单(您甚至不需要单独的页面或单独的代码) - 或者 jQuery 对于客户端同样出色,但正如您所说是一种学习练习。【参考方案2】:最好的办法是创建一个处理程序文件 (*.ashx) 来处理传入的请求并将正确格式化的 json/xml 返回到 javascript。 ScriptManager 用于提供这些内容直接嵌入到实际页面中,但是(除非您打算完全重建 ScriptManager)您会发现通过处理程序来完成它并绕过标准请求的 IIS 处理更简单。
【讨论】:
是的,你是对的。通用处理程序非常适合 ajax,因为它比 asp.net 页面轻量级。 我一定会试试这个!非常感谢!【参考方案3】:ASP.Net 中的一个功能是能够从客户端代码调用服务器端代码而无需回发,使用称为客户端回调的东西。到目前为止,我发现了一些小警告:-
它使用目前只有 IE 的 XmlHttp。 Firefox 和其他浏览器有替代方案,但回调仅使用此方案。 您可以从服务器返回的唯一类型是字符串(但如果需要,我们可以通过序列化来解决这个问题)我使用的示例是我有两个需要保持同步的相关文本框。如果更改了 ClientID 框,则 ClientName 框应显示具有该 ID 的客户端的名称,反之亦然。
要开始使用此功能,请确保您的代码隐藏实现 ICallbackEventHandler 接口:-
public partial class WebForm1 : System.Web.UI.Page, ICallbackEventHandler
接下来,我在我的 aspx.cs 中的 Page_Load 方法中注册我的回调方法:-
// Set up client callbacks. These allow client-side scripts to call
// server-side functions and retrieve the results. Its a string-only
// return I'm afraid, limited by the ICallbackEventHandler method signatures
txtClientID.Attributes.Add("onchange", "GetClientNameById('id|' + this.value, 'id');");
string callBackClientID = Page.ClientScript.GetCallbackEventReference(this, "arg", "ClientNameCallback", "context", "ClientNameCallbackError", true);
string clientIDfunction = "function GetClientNameById(arg,context) " + callBackClientID + "; ";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "GetClientNameById", clientIDfunction, true);
txtClientName.Attributes.Add("onchange", "GetClientIdByName('name|' + this.value, 'name');");
string callBackClientName = Page.ClientScript.GetCallbackEventReference(this, "arg", "ClientIdCallback", "context", "ClientIdCallbackError", true);
string clientNamefunction = "function GetClientIdByName(arg, context) " + callBackClientName + "; ";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "GetClientIdByName", clientNamefunction, true);
这会将服务器函数注册到页面并将它们连接到客户端回调方法 - 这些回调方法是基本的占位符,除了给服务器一个返回字符串的地方之外什么都不做。所以在 aspx 页面本身:-
<script type="text/javascript">
function ClientNameCallback(result, context)
//sorry about the hardcoded element name...
if(result != "")
document.getElementById('ctl00_ContentPlaceHolder1_txtClientName').setAttribute('value',result);
function ClientIdCallback(result,context)
//sorry about the hardcoded element name...
if(result != "")
document.getElementById('ctl00_ContentPlaceHolder1_txtClientID').setAttribute('value',result);
function ClientNameCallbackError(result, context)
//Not sure what error is likely to arise at this point, but...
alert('Error in client name callback function - please say that to eSolutions!');
function ClientIdCallbackError(result, context)
//Not sure what error is likely to arise at this point, but...
alert('Error in client id callback function - please say that to eSolutions!');
</script>
最后,我们实现所需的 ICallbackEventHandler,其中包含我们要执行的服务器端处理:-
string ICallbackEventHandler.GetCallbackResult()
return callbackReturnValue;
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
// eventArgument should be in format field|value,
// e.g., "id|30102" or "name|test client"
// This is because of the "single string" limitations
// of the callback interface
if(eventArgument.StartsWith("name"))
//....do lookup to get the id based on the name, from an array or database, or whatever
callbackReturnValue = <string we want to pass back to client-side
else if(eventArgument.StartsWith("id"))
等等。 等等
【讨论】:
我得看看我是否比使用 Andy Shellam 描述的单独页面方式更喜欢这种方式【参考方案4】:赞 this answer,+1 表示自己动手。
但是,我必须强烈建议您在客户端使用像 jQuery 这样的库来解决浏览器之间的差异(在这种特定情况下,存在差异)。它(或其他库)将提供一种抽象,您可以在所有 Web 浏览器中使用它来规范您的代码。
话虽如此,在 ASP.NET 中,您可以检查调用是否是回发,如果是,只需将内容写入输出流。
然而,我强烈建议不要这样做。相反,对 ajax 的调用应该完全指向另一个页面,因为它提供了不同的目的、不同类型的响应,因此应该有自己的 URL。
另外,请注意,当以 XML 或 JSON 形式返回内容时(这在 Ajax 调用中很常见,现在 JSON 占主导地位),将响应的 ContentType 属性更改为适当的 mime 类型很重要(“text/xml”用于 XML,“application/json”用于 JSON)。
请注意,ASP.NET MVC 使这一切变得更加容易,您可能希望考虑使用它而不是 WebForms 模型,因为 MVC 是从头开始构建的,可以更轻松地处理其中许多场景。它允许您将处理页面呈现的方法与以 Ajax 调用形式提供功能的方法完全分开(这只是众多好处之一)。
【讨论】:
是的,在我完全了解如何手动完成并弄清楚所有内部工作原理之后,我很可能会转向 jQuery 之类的库。非常感谢。【参考方案5】:如果我的想法是正确的,您可以通过检查标头 X-Requested-With
来区分普通 HTTP 请求和 AJAX 调用。
因此,在您的玩具示例中,如果您想对 AJAX 请求做出不同的响应:
public void Page_Load(object sender, EventArgs e)
if (Request.Headers["X-Requested-With"] == "XMLHttpRequest")
Response.Clear(); // dont want <html>.... etc stuff
Response.Write("Hi from AJAX!");
else
// normal page stuff
然后,在你的 js 中,像这样(请原谅任何语法错误)
var req = new XmlHttpRequest();
req.open("GET","default.aspx",false);
req.send("");
document.getElementById('some_div').innerHTML = req.responseXML;
【讨论】:
嗯.. 不幸的是我无法让它工作。我需要做更多的调查,因为这似乎是一种有效的方法。非常感谢! @Tomaszewski 哪个部分不起作用?如果您在 CS 代码中设置断点,是否触发了正确的代码块? 您好,感谢您的回复。在调试时,我的 Request.Headers 似乎没有一个名为“X-Requested-With”的键,除非我遗漏了什么。 虽然,我找到了这篇文章 (haacked.com/archive/2009/01/27/aspnetmvc-release-candidate.aspx),它似乎在谈论在 ASP.NET MVC 中这是有效的。我还没有尝试过 MVC。但是,它表明 WebForms 可能有一个自定义的“X-Requested-With”......或类似的东西。不确定我理解正确。以上是关于在 ASP.NET 和 C# 中手动进行 AJAX 调用的主要内容,如果未能解决你的问题,请参考以下文章
使用 jQuery 在 ASP.NET 中进行 AJAX 回调
ASP.NET C# SuppressFormsAuthenticationRedirect 不适用于 Ajax POST?
我需要使用 C# 和 ASP.Net 构建一个非常轻量级的 Ajax 引擎。你有啥建议?