英文:
Best-Practice for implementing UI-Fragments into HTML in VB.NET Web Forms Website
问题
我有一个使用VB.NET 4.7.1和Web Forms模板的遗留网站。最近,我被要求将第三方API的功能集成到网站中。这是该网站首次使用API,以前没有使用过HttpClient/WebRequest。
有两个主要要求:
- 我必须通过Keycloak令牌对API进行身份验证。这是通过GET请求来获取访问令牌,然后我可以将其传递给其他API来实现的。
- 我必须通过GET和POST请求的组合来访问API,以构建要使用的UI片段。
我找到了一些"解决方法",允许我执行这些操作。然而,Web Forms显然不是为客户端消耗服务器端API进行DOM操作而构建的。我对这项技术还很陌生,所以我正在寻找如何处理这种情况的最佳实践。目前,我只能通过获取令牌然后直接输入到客户端JavaScript中才能使其工作。这显然不适合生产就绪的网站。
英文:
I've got a legacy website that uses VB.NET 4.7.1 with the Web Forms template. I've recently been asked to implement functionality from a third party API into the website. This is the first time the website has ever consumed an API, there were no previous instances of HttpClient/WebRequest being used.
There are two primary requirements:
- I have to authenticate the API through a keycloak token. This is being done by a GET request to get an access token that I can pass to the other APIs.
- I have to make a combination of GET and POST requests to the API in order to build the UI-fragments that I have been asked to use.
I've found a few "Work-arounds" that allow me to do this. However, Web Forms is clearly not built to have the client-side consume Server-Side API's for DOM manipulation. I am new to the technology, so I'm looking for the best practice on how to handle this. Currently I can only get it to work by grabbing the token then entering it directly into the client-side javascript. That is obviously un-ideal for a production ready website.
答案1
得分: 1
Web Forms 明显不是为了让客户端使用服务器端 API 进行 DOM 操作而构建的。
嗯,我不能确定在这里使用 Web Forms,或者决定使用 React 或其他框架是否是一个问题(这些框架可以与 Web Forms 一起使用)。
我的意思是,你总是可以向任何现有页面添加一个简单的 Web 方法,然后通过 AJAX 调用该代码后台。在大多数情况下,你不需要在 Web Forms 中这样做,因为它使一切都变得非常简单和容易。
然而,这种便利的“大”缺点当然是,通常你会遭受更多的后台提交(往返),而不是决定将更多的功能和代码推送到客户端(浏览器 + JavaScript)。
但是,几乎没有什么阻止你采用一些这些较新的技术,甚至开始使用和采用更多的客户端 JavaScript 代码。
比如,假设我们想在网页上加载一些控件。
我们可以添加一个按钮,单击按钮,后台代码运行,更新控件,页面返回到客户端,然后我们的控件被填充了一些值。
但是,假设你不想要 Web Forms 非常著名的“经典”后台提交和往返?
所以,我们可以让按钮单击运行客户端代码,它可以向代码后台发出 AJAX 调用,获取数据,然后更新控件。
实际上,如果你正在使用 Web Forms 或其他开发堆栈,这并不是什么大问题。
所以,假设我们想获取一条记录,并填写一些文本框 - 但是让我们使用 AJAX 调用(即使是 10 年前的 Web Forms 模板也包括 jQuery,但如果没有,我将假设我们可以在此页面上使用 jQuery)。
所以,假设这是标记和一个 AJAX 调用:
<h4>选择战斗机</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) {
// 从服务器获取记录,更新 DOM 值
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>
网页的代码后台:
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
现在的结果如下:
所以,上面的示例中,我从服务器端获取了一些数据(一个类),然后使用 jQuery 填充了页面上的一些控件。
当然,上述代码也可以做相反的事情。
没有后台提交,没有往返,我们使用了 jQuery 的 AJAX 调用和页面上的一个简单的 Web 方法。所以,我们完全忽略了传统的 Web Forms 方法,在这里没有什么限制或阻碍你使用 Web 方法调用(AJAX)在 Web Forms 页面中。
因此,你可以自由地添加一些 JavaScript 到客户端,调用代码后台(Web 方法)。而且这个 Web 方法可以将一个普通的类返回给 JavaScript(请注意,它以 JSON 格式返回数据)。
为了减少键盘输入,我在上面使用了 jQuery
英文:
> Web Forms is clearly not built to have the client-side consume Server-Side API's for DOM manipulation.
Hum, I can't really say using webforms, or even deciding to say adopt react or some other framework here is a issue. (such frameworks can be used with web forms).
I mean, you can always add a simple web method to ANY existing page, and then say make a ajax call to that code behind. In most cases, you don't need to do this in webforms, since it makes everything oh so easy and simple.
However, the "big" downside of this ease is of course that you often will suffer a lot more post-backs (round trips) then if you decided to push more features and code to the client side (Browser + JavaScript).
However, little stops you from adopting some of these newer technologies, or even say starting to use + adopt more JavaScript client side code.
I mean, let's say we wanted to load up some controls on the web page.
We could drop a button, click on the button, post-back, code behind runs, updates the controls, page travels back to client, and we have our controls filled out with some values.
However, let's say you don't want the "classic" post-back and round trip that webforms are so famous for?
So, we can have that button click run client side code, it can make a ajax call to the code behind, get the data, and update the controls.
Really, not much of a big deal if this is a web forms, or some other dev stack you are using.
So, say we want to grab a record, and fill out a few text boxes - but let's use a ajax call. (even templates from 10 years ago for webforms included jQuery, but if not, I'll assume we have jQuery available for use on this page).
So, say this markup and an ajax call:
<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>
Code behind on web 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
And the result is now this:
So, in above, I pulled some data from the server side (a class), and then used jQuery to fill out a few controls on the page.
And certainly the above could do the reverse.
There are no post-backs, no round trips, and we used a jQuery ajax call and a simple web method on the page. So, we 100% ignored the traditional webforms approach here, and there not really anything I can think of that restricts, or removes your ability to use web method calls (ajax) in a webforms page.
So, you are free to toss in some JavaScript to the client side, call code behind (web method). And that web method can return a plain class to the JavaScript. (note it returned the data as JSON).
And to save a bit of keyboard here I used jQuery in the above.
Now, I think to call some external web method, you probably still better off to do this with server side code, and then perhaps toss in some client side JavaScript code.
As above shows, we certainly are able to mix both "modern" side JavaScript code, ajax calls, and also have a mix of server side code. And as above shows, even vb.net and webforms allows ajax calls to code behind, and even returning some structured data to the client side was rather easy.
I should also point out without ANY extra work, that web method example supports not only a web method call, but ALSO can be called and used as a REST end point. (and no changes to that code is required).
In fact, that web method will also support a SOAP (XML) call, but then again, who uses those?
But, despite this being webforms, that web method supports SOAP, JSON/ajax (web method call), and even supports using a REST call to the above web method. And ZERO code changes are required to the code behind to support all 3 cases.
So that web method will accept ajax, REST (end point), or SOAP as written. So even using a REST call to that web method (the end point) works here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论