希望你能帮助我解决这个问题。我正在尝试使用 AJAX 和 VB.NET 从服务器端获取列表到 javascript。我尝试了几件事,但它总是返回完整的文件而不是列表。
我尝试使用 Javascript 和 Jquery AJAX,但总是得到相同的结果。 简历中: 连接 DAL.vb 文件 -> 调用 Presenter.vb 上的 DAL -> 返回到后面的 ASCX.VB 文件代码。
**My Presenter:**
Public Function GetMenuFromDB() As String
....authorization code
valueToSet = _accDAL.GetMenuDetailsByUser(UserID) -> my connection to DB
End If
If valueToSet.Count > 0 Then
Dim serializer As New JsonSerializerOptions()
Dim json As String = Text.Json.JsonSerializer.Serialize(valueToSet)
Return json
End If
End Function
**My file ascx.vb:**
<WebMethod()>
Protected Shared Function GetMenuFromDB(sender As Object, e As EventArgs) As String
Dim presenter As New MenuPresenter()
Return presenter.GetMenuFromDB()
End Function]
**My JS:**
function getMenuByUser() {
var xhr = new XMLHttpRequest();
var url = "~/Menu.ascx/GetMenuFromDB"
xhr.open("GET", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
xhr.send();
}
OR Jquery:
$(document).ready(function () {
$.ajax({
type: "GET",
dataType: "json",
contentType: "application/json; charset=utf-8",
url: "~/Menu.ascx/GetMenuFromDB",
success: function (result) {
debugger;
console.log(result);
},
error: function (xhr, textStatus, error) {
console.log(error);
}
});
});
但是我在ascx.vb 上设置了断点,却一直没有进入。 我更改了不同类型的 URL,但不起作用。 另外,我尝试移动该方法以指向 aspx 文件而不是 ascx,以防万一,但它的结果相同。
谢谢。
您有几个问题。
整个页面正在被返回,当ajax调用混乱或者甚至无效时,这种情况往往会发生(因此整个网页只是刷新并返回到客户端。所以,当你没有有效的 JavaScript 代码。
还有一些事情:
JavaScript 中使用的路径名称与客户端 (JavaScript) 代码的语法和格式不同。
例如,您使用“~/”。不幸的是,这在客户端代码中无效。
几乎在所有情况下,您要使用的路径名都需要是当前页面,或者相对于当前页面。
如果您的当前页面位于测试文件夹内,那么您必须(比如说)向下一个文件夹到根目录。
如果我们当前的页面位于名为“Testing”的文件夹中,那么我们必须使用此:
url: "../Menu.ascx/GetMenuFromDB"
“~/”仅适用于由 ASP.NET 和您的代码处理的服务器端代码(代码隐藏)。
事实上,对于 asp:Image 控件与非 asp:Image 控件来说,也存在上述相同的问题!
例如,您不能使用:
<img src="~/Content/Pictures/dog.png">
但是,如果您使用 asp.net 控件,则上述内容有效。
在大多数情况下,这并不是什么大问题,但它通常会成为一个问题,尤其是在使用母版页时。
由于您的母版页路径通常是根目录,但是在任何文件夹中嵌套几个文件夹的任何旧页面仍然可以经常使用母版页吗?那么你的路径名可能会变得混乱。
例如,我想在所有页面中都有一个 JavaScript toast 消息例程。
在我的主页中,我有这个:
<%: Scripts.Render("/Scripts/jquery.toast.min.js") %>
<%: Styles.Render("~/Scripts/jquery.toast.min.css") %>
请注意,我不只是添加上述脚本标记参考。 (因为我不想要一个混乱的路径名)。
现在,让我们处理您的 ajax 示例。
首先,在大多数情况下,您不需要序列化类,因为这是默认设置,并且由服务器自动完成。
在许多情况下,如果仅在给定页面中使用/调用 Web 方法,那么我会将 Web 方法放入该给定页面中,从那时起,在查看页面标记时,我可以轻松翻转到后面的代码,我不必四处寻找包含 web 方法的 ascx 页面。
好处是一般来说我不必担心 JavaScript 中的路径名问题,因为它在同一页面上,因此无论如何都不需要路径名!
我们在测试页上做一个例子,因此不使用ascx。
牢记以上:
我们不能也不会在 JavaScript 中使用“~/”——不允许这样的语法。
任何 Web 方法都会为您自动序列化 - 无需在此处使用 JavaScript 或 NewtonSoft 序列化程序。
还有一个问题似乎总是让我费时间,而且总是忘记:检查 RouteConfig.vb 中的route.config 例程。你会看到/发现这个:
settings.AutoRedirectMode = RedirectMode.Permanent
将上面更改为:
settings.AutoRedirectMode = RedirectMode.Off
最后提示:
返回到 Web 方法调用的数据以 MyResult.d 形式返回
注意.d
您的返回数据在“.d”中返回。这只是 .net 的事情。
让我们设置一个简单的页面,在页面上放置一些控件。因此,当我们选择下拉列表时,我们将在 100% 客户端执行此操作,无需回发,也无需往返。
对于服务器端与客户端寻址,这里是页面标记:
<head runat="server">
<title></title>
<script src="../Scripts/jquery-3.4.1.js"></script>
<link href="../Content/bootstrap.css" rel="stylesheet" />
<script src="../Scripts/bootstrap.js"></script>
</head>
<body>
<form id="form1" runat="server">
<div style="padding:35px">
<h4>Select fighter</h4>
<asp:DropDownList ID="cboFigher" runat="server" Width="300"
DataTextField="Fighter"
DataValueField="ID"
onchange="mychange(this)"
>
</asp:DropDownList>
<br />
<br />
<div class="mybox" style="float:left;border:solid 1px">
<div style="text-align: center; padding: 2px 10px 12px 10px">
<h3 id="Fighter" runat="server"></h3>
<asp:Image ID="Image2" runat="server"
Width="180" Height="120" />
<h4>Engine</h4>
<asp:Label ID="EngineLabel" runat="server" Text="" />
<h4>Description</h4>
<asp:Label ID="DescLabel" runat="server" width="400px"
Text="" style="text-align:left" Font-Size="Large" />
</div>
</div>
<script>
function mychange(myitem) {
// get record from server, update
// dom values
var iPK = myitem.value
$.ajax({
type: "POST",
url: "FighterOneAJ.aspx/GetFighter",
data: JSON.stringify({ PK : iPK}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (rData) {
var F = rData.d
$('#Image2').attr("src", F.ImagePath)
$('#Fighter').text(F.Fighter)
$('#EngineLabel').text(F.Engine)
$('#DescLabel').text(F.Description)
},
failure: function (rData) {
alert("error " + rData.d);
}
});
}
</script>
</div>
</form>
现在该页面的代码如下:
我在后面包含了完整的页面代码:
Imports System.Web.Services
Public Class FighterOneAJ
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
cboFigher.DataSource =
MyRst("SELECT ID, Fighter FROM Fighters ORDER BY Fighter")
cboFigher.DataBind()
cboFigher.Items.Insert(0, New ListItem("Select Fighter", "0"))
End If
End Sub
<WebMethod()>
Public Shared Function GetFighter(PK As String) As clsFigher
Dim OneFigher As New clsFigher
OneFigher.ID = PK
Return OneFigher
End Function
Public Class clsFigher
Public Fighter As String
Public Engine As String
Public Thrust As String
Public Description As String
Public ImagePath As String
Private m_id As Integer
Public Property ID As Integer
Get
Return m_id
End Get
Set(value As Integer)
m_id = value
Dim cmdSQL As New _
SqlCommand("SELECT * FROM Fighters WHERE ID = @ID")
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = m_id
With MyRstP(cmdSQL).Rows(0)
Fighter = .Item("Fighter")
Engine = .Item("Engine")
Thrust = .Item("Thrust")
Description = .Item("Description")
ImagePath = Replace(.Item("ImagePath"), "~/", "../")
End With
End Set
End Property
End Class
End Class
上面的效果和结果是这样的:
注意上面服务器端类的返回。请注意,我不必转换为 JSON,甚至不需要序列化我返回到客户端的类。
还要注意,即使您只返回一个字符串,或者如本示例所示,一个类:您使用 rData.d,“.d”部分就是返回值。
我想我可以在该代码中使用 rData.d.Fighter 例如。
如果您想避免脚本引用的相对路径名,那么我们可以更改此:
<title></title>
<script src="../Scripts/jquery-3.4.1.js"></script>
<link href="../Content/bootstrap.css" rel="stylesheet" />
<script src="../Scripts/bootstrap.js"></script>
至:
<title></title>
<%: Scripts.Render("~/Scripts/jquery-3.4.1.js") %>
<%: Styles.Render("~/Content/bootstrap.css") %>
<%: Scripts.Render("~/Scripts/bootstrap.js.js") %>
总结:
客户端 JS 代码中不能使用“~/”。
您必须更改routeConfig.vb中的设置
你必须使用“.d”
您不必序列化类或内容 - 这是自动为您完成的。