在ASP中手动进行AJAX调用。净和c#

时间:2022-06-04 13:21:29

I want to write my own AJAX in ASP.NET, and not use the ASP.NET ScriptManager, etc.

我想在ASP中编写我自己的AJAX。NET,不要使用ASP。净ScriptManager等等。

WHY? I like doing stuff manually and knowing how stuff works from the inside, so I just want to do it for myself.

为什么?我喜欢手工做东西,并且知道内部是如何工作的,所以我只想自己做。

So my question is, after I make an AJAX call:

我的问题是,在我打了一个AJAX电话之后

var ajaxCall = new XMLHttpRequest();
....
ajaxCall.send(null)

How can I, in C#, add in the Page_Load (or not) so that it listens for this and returns a String for example.

在c#中,我如何添加Page_Load(或不添加),以便它监听这个并返回一个字符串,例如。

5 个解决方案

#1


4  

+1 for you doing things yourself - I like to know that I can do things myself before using frameworks that do it for me, so if it goes tits up, I roughly know how to begin fixing it.

+1对于你自己做的事情——我想知道,在使用为我做的框架之前,我可以自己做一些事情,所以如果事情进展顺利,我大概知道如何开始修复它。

Anyway down to your question. Just output data normally using ASP.NET or Response.Write. If you're doing a POST request, you can check for this in the Page_Load using if (Page.IsPostBack.) Remember that typically you'll only be sending the data for part of a page, not the whole page itself, so you won't need the <html>, <head> or <body> tags.

总之,你的问题。输出数据通常使用ASP。净或Response.Write。如果您正在执行一个POST请求,可以使用If (Page.IsPostBack)在Page_Load中检查这个请求。请记住,通常您只发送部分页面的数据,而不是整个页面本身,因此您不需要、或标记。

When I've seen this done in ASP.NET websites before, separate pages have been used for the AJAX calls (e.g. index.aspx = normal site, index-ajax.aspx = ajaxified page component.)

当我在ASP中看到这个的时候。NET网站之前,AJAX调用都使用单独的页面(如索引)。标准站点,索引-ajax。aspx = ajaxified page组件)

if (Page.IsPostBack)
{
    Response.Write("Hello, world!  From AJAX.");
}

You don't have to use Page.IsPostBack, most AJAX requests are just GET's, so if you put in your Page_Load:

你不需要使用页面。IsPostBack,大多数AJAX请求都是GET的,所以如果你输入Page_Load:

Response.Write("Hello, world!  From AJAX.");

Then do an AJAX call for that page, you'll get "Hello, world! From AJAX." returned from the AJAX call.

然后为该页面执行AJAX调用,您将得到“Hello, world!”从AJAX调用返回。

#2


6  

Like this answer, +1 for doing it yourself.

像这个答案,+1自己做。

However, I must strongly advise you to use a library like jQuery on the client-side to account for differences across browsers (and in this specific case, there are differences). It (or other libraries) will provide an abstraction you can use across all web browsers to normalize your code.

但是,我必须强烈建议您在客户端使用jQuery这样的库来解释不同浏览器之间的差异(在这个特定的例子中,存在差异)。它(或其他库)将提供一个抽象,您可以在所有web浏览器中使用它来规范化代码。

That being said, in ASP.NET, you could check to see if the call is a post back, and if it is, just write the content to the output stream.

也就是说,在ASP中。NET,您可以检查调用是否为post返回,如果是,则将内容写入输出流。

However, I would strongly recommend against that. Rather, the call to ajax should be to another page completely, as it's providing a different purpose, a different kind of response, and therefore, deserves it's own URL.

然而,我强烈建议不要这么做。相反,对ajax的调用应该完全指向另一个页面,因为它提供了不同的目的、不同的响应,因此,它应该拥有自己的URL。

Also, mind you, that when returning content in the form of XML or JSON (which is typical for Ajax calls, with JSON being pretty dominant now), it's important to change the ContentType property of the response to the appropriate mime type ("text/xml" for XML, "application/json" for JSON).

另外,请注意,当以XML或JSON的形式返回内容时(这是Ajax调用的典型形式,现在JSON占主导地位),将响应的内容类型属性更改为适当的mime类型(XML的“text/ XML”,JSON的“application/ JSON”)是很重要的。

Note that ASP.NET MVC makes this all much, much easier, and you might want to look into using that instead of the WebForms model, as MVC is built from the ground up to handle many of these scenarios much easier. It allows you to cleanly separate methods which process page rendering, from those that provide functionality in the form of Ajax calls (and this is just one of the many benefits).

注意,ASP。NET MVC使这一切变得更加容易,您可能想要使用它而不是WebForms模型,因为MVC是从头构建的,以处理许多这样的场景。它允许您干净地将处理页面呈现的方法与提供Ajax调用形式功能的方法(这只是众多好处之一)分离开来。

#3


1  

Your best bet would be to create a handler file (*.ashx) that would process the incoming request and return the properly formatted json/xml to the JavaScript. The ScriptManager is used to provide this stuff embedded directly into the actual page, but (unless you intend to rebuild the ScriptManager entirely) you'll find it simpler to do it through a handler and bypass the IIS processing of the standard request.

最好的方法是创建一个处理程序文件(*.ashx),该文件将处理传入的请求并将经过适当格式的json/xml返回给JavaScript。ScriptManager用于将这些内容直接嵌入到实际的页面中,但是(除非您打算完全重新构建ScriptManager),您会发现通过处理程序完成它并绕过标准请求的IIS处理会更简单。

#4


1  

If I'm right in my thinking, you can distinguish between a normal HTTP request an an AJAX call by examining the header X-Requested-With.

如果我的想法是对的,您可以通过检查x - requestewith头来区分普通的HTTP请求和AJAX调用。

So, in your toy example if you wanted to respond differently to an AJAX request:

因此,在您的玩具示例中,如果您希望对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
    }
}

then, in your js, something like this (forgive any syntax errors please)

然后,在您的js中,类似这样(请原谅任何语法错误)

var req = new XmlHttpRequest();
req.open("GET","default.aspx",false);
req.send("");
document.getElementById('some_div').innerHTML = req.responseXML;

#5


0  

One of the features in ASP.Net is the ability to call server-side code from client-side code without postback, using something called a client callback. There's a couple of minor caveats I've found so far though :-

ASP的一个特性。Net是使用称为客户端回调的东西从客户端代码调用服务器端代码而不进行回发的能力。到目前为止,我发现了一些小问题:-

  • it uses XmlHttp which is IE only at the moment. Firefox and other browsers have an alternative, but the callbacks are using this only.
  • 它使用的是XmlHttp,而后者目前还只是IE。Firefox和其他浏览器有另一种选择,但是回调只使用这个。
  • the only type you can return from the server is a string (but we can get around that by serializing if necessary)
  • 您可以从服务器返回的唯一类型是字符串(但是如果需要,我们可以通过序列化来解决)

The example I've used is where I have two related textboxes that need to be kept in sync. If the ClientID box is changed, the ClientName box should display the name of the client that has that ID, and vice-versa.

我使用的示例是有两个相关的文本框需要保持同步。如果更改了ClientID框,则ClientName框应该显示具有该ID的客户机的名称,反之亦然。

To start using this functionality, ensure your code-behind implements the ICallbackEventHandler interface :-

要开始使用此功能,请确保您的代码支持实现了ICallbackEventHandler接口:-。

public partial class WebForm1 : System.Web.UI.Page, ICallbackEventHandler

Next, I register my callback methods in the Page_Load method in my aspx.cs :-

接下来,我在aspx中的Page_Load方法中注册回调方法。cs:-

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

This registers the server functions with the page and hooks them up to the client callback methods - these callback methods are basic placeholders that do nothing but give the server somewhere to return its string to. So on the aspx page itself :-

这将用页面注册服务器函数,并将它们与客户端回调方法关联起来——这些回调方法是基本的占位符,除了给服务器一个返回其字符串的地方之外什么都不做。所以在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>

Finally, we implement the required ICallbackEventHandler, which contains the server-side processing we want to perform :-

最后,我们实现了所需的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"))

etc. etc.

等等。

#1


4  

+1 for you doing things yourself - I like to know that I can do things myself before using frameworks that do it for me, so if it goes tits up, I roughly know how to begin fixing it.

+1对于你自己做的事情——我想知道,在使用为我做的框架之前,我可以自己做一些事情,所以如果事情进展顺利,我大概知道如何开始修复它。

Anyway down to your question. Just output data normally using ASP.NET or Response.Write. If you're doing a POST request, you can check for this in the Page_Load using if (Page.IsPostBack.) Remember that typically you'll only be sending the data for part of a page, not the whole page itself, so you won't need the <html>, <head> or <body> tags.

总之,你的问题。输出数据通常使用ASP。净或Response.Write。如果您正在执行一个POST请求,可以使用If (Page.IsPostBack)在Page_Load中检查这个请求。请记住,通常您只发送部分页面的数据,而不是整个页面本身,因此您不需要、或标记。

When I've seen this done in ASP.NET websites before, separate pages have been used for the AJAX calls (e.g. index.aspx = normal site, index-ajax.aspx = ajaxified page component.)

当我在ASP中看到这个的时候。NET网站之前,AJAX调用都使用单独的页面(如索引)。标准站点,索引-ajax。aspx = ajaxified page组件)

if (Page.IsPostBack)
{
    Response.Write("Hello, world!  From AJAX.");
}

You don't have to use Page.IsPostBack, most AJAX requests are just GET's, so if you put in your Page_Load:

你不需要使用页面。IsPostBack,大多数AJAX请求都是GET的,所以如果你输入Page_Load:

Response.Write("Hello, world!  From AJAX.");

Then do an AJAX call for that page, you'll get "Hello, world! From AJAX." returned from the AJAX call.

然后为该页面执行AJAX调用,您将得到“Hello, world!”从AJAX调用返回。

#2


6  

Like this answer, +1 for doing it yourself.

像这个答案,+1自己做。

However, I must strongly advise you to use a library like jQuery on the client-side to account for differences across browsers (and in this specific case, there are differences). It (or other libraries) will provide an abstraction you can use across all web browsers to normalize your code.

但是,我必须强烈建议您在客户端使用jQuery这样的库来解释不同浏览器之间的差异(在这个特定的例子中,存在差异)。它(或其他库)将提供一个抽象,您可以在所有web浏览器中使用它来规范化代码。

That being said, in ASP.NET, you could check to see if the call is a post back, and if it is, just write the content to the output stream.

也就是说,在ASP中。NET,您可以检查调用是否为post返回,如果是,则将内容写入输出流。

However, I would strongly recommend against that. Rather, the call to ajax should be to another page completely, as it's providing a different purpose, a different kind of response, and therefore, deserves it's own URL.

然而,我强烈建议不要这么做。相反,对ajax的调用应该完全指向另一个页面,因为它提供了不同的目的、不同的响应,因此,它应该拥有自己的URL。

Also, mind you, that when returning content in the form of XML or JSON (which is typical for Ajax calls, with JSON being pretty dominant now), it's important to change the ContentType property of the response to the appropriate mime type ("text/xml" for XML, "application/json" for JSON).

另外,请注意,当以XML或JSON的形式返回内容时(这是Ajax调用的典型形式,现在JSON占主导地位),将响应的内容类型属性更改为适当的mime类型(XML的“text/ XML”,JSON的“application/ JSON”)是很重要的。

Note that ASP.NET MVC makes this all much, much easier, and you might want to look into using that instead of the WebForms model, as MVC is built from the ground up to handle many of these scenarios much easier. It allows you to cleanly separate methods which process page rendering, from those that provide functionality in the form of Ajax calls (and this is just one of the many benefits).

注意,ASP。NET MVC使这一切变得更加容易,您可能想要使用它而不是WebForms模型,因为MVC是从头构建的,以处理许多这样的场景。它允许您干净地将处理页面呈现的方法与提供Ajax调用形式功能的方法(这只是众多好处之一)分离开来。

#3


1  

Your best bet would be to create a handler file (*.ashx) that would process the incoming request and return the properly formatted json/xml to the JavaScript. The ScriptManager is used to provide this stuff embedded directly into the actual page, but (unless you intend to rebuild the ScriptManager entirely) you'll find it simpler to do it through a handler and bypass the IIS processing of the standard request.

最好的方法是创建一个处理程序文件(*.ashx),该文件将处理传入的请求并将经过适当格式的json/xml返回给JavaScript。ScriptManager用于将这些内容直接嵌入到实际的页面中,但是(除非您打算完全重新构建ScriptManager),您会发现通过处理程序完成它并绕过标准请求的IIS处理会更简单。

#4


1  

If I'm right in my thinking, you can distinguish between a normal HTTP request an an AJAX call by examining the header X-Requested-With.

如果我的想法是对的,您可以通过检查x - requestewith头来区分普通的HTTP请求和AJAX调用。

So, in your toy example if you wanted to respond differently to an AJAX request:

因此,在您的玩具示例中,如果您希望对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
    }
}

then, in your js, something like this (forgive any syntax errors please)

然后,在您的js中,类似这样(请原谅任何语法错误)

var req = new XmlHttpRequest();
req.open("GET","default.aspx",false);
req.send("");
document.getElementById('some_div').innerHTML = req.responseXML;

#5


0  

One of the features in ASP.Net is the ability to call server-side code from client-side code without postback, using something called a client callback. There's a couple of minor caveats I've found so far though :-

ASP的一个特性。Net是使用称为客户端回调的东西从客户端代码调用服务器端代码而不进行回发的能力。到目前为止,我发现了一些小问题:-

  • it uses XmlHttp which is IE only at the moment. Firefox and other browsers have an alternative, but the callbacks are using this only.
  • 它使用的是XmlHttp,而后者目前还只是IE。Firefox和其他浏览器有另一种选择,但是回调只使用这个。
  • the only type you can return from the server is a string (but we can get around that by serializing if necessary)
  • 您可以从服务器返回的唯一类型是字符串(但是如果需要,我们可以通过序列化来解决)

The example I've used is where I have two related textboxes that need to be kept in sync. If the ClientID box is changed, the ClientName box should display the name of the client that has that ID, and vice-versa.

我使用的示例是有两个相关的文本框需要保持同步。如果更改了ClientID框,则ClientName框应该显示具有该ID的客户机的名称,反之亦然。

To start using this functionality, ensure your code-behind implements the ICallbackEventHandler interface :-

要开始使用此功能,请确保您的代码支持实现了ICallbackEventHandler接口:-。

public partial class WebForm1 : System.Web.UI.Page, ICallbackEventHandler

Next, I register my callback methods in the Page_Load method in my aspx.cs :-

接下来,我在aspx中的Page_Load方法中注册回调方法。cs:-

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

This registers the server functions with the page and hooks them up to the client callback methods - these callback methods are basic placeholders that do nothing but give the server somewhere to return its string to. So on the aspx page itself :-

这将用页面注册服务器函数,并将它们与客户端回调方法关联起来——这些回调方法是基本的占位符,除了给服务器一个返回其字符串的地方之外什么都不做。所以在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>

Finally, we implement the required ICallbackEventHandler, which contains the server-side processing we want to perform :-

最后,我们实现了所需的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"))

etc. etc.

等等。