由ASP.NET所谓前台调用后台、后台调用前台想到HTTP——实践篇(二)

简介:

由ASP.NET所谓前台调用后台、后台调用前台想到HTTP——理论篇中描述了一下ASP.NET新手的三个问题及相关的HTTP协议内容,在由ASP.NET所谓前台调用后台、后台调用前台想到HTTP——实践篇(一)中已经解答了关于服务器怎么改变页面元素或“调用”JavaScript的问题,为了避免上篇啰啰嗦嗦一大推,这次直奔主题——ASP.NET前台如何调用后台方法

问题细化

所谓前台调用后台这种问题的提出无非是因为很多新手受了ASP.NET服务器端控件的“误导”,你不是说前台没有把JavaScript语句、页面元素什么的传到后台,所以前台调用后台,或者后台监视页面变化是扯淡嘛!那ASP.NET中为什么服务器端控件一点击就能调用后台制定方法呢?按照你前面的理论即使用了服务器端控件,那么到了浏览器页面也变成最普通不过的HTML文本了,怎么还能够调用服务器端方法呢?!

确实,浏览器呈现的是HTML文本,我们先不用拘泥于ASP.NET怎么做到的前台“调用”后台,我们可以自己实现一下,不过在此之前我们得明白一些过于Post的问题

简单聊聊Post

我们在看很多网页的时候都会看到这样的内容

<form id="form1" method="post" action="Default.aspx">
        <input type="text" name="wd" />
         <input type="submit" name="test" value="test" />
    </form>

这段HTML文本同学们都能看懂,页面上有一个form,form内有两个input,点击submit的时候,页面form内容会以post方式被提交到Default.aspx这个页面。

HTTP协议中的Post方法会将所处的form提交到form指定页面,如果form指定的方法为post(还可能是get等),那么form内有些数据会一并被提交。

既然不是整个form被提交,那么哪些数据会被提交呢?

1.input的name和value

2.input type=”submit” 只有被点击的时候才将其本身name与value提交

3.对于多个name相同的input type=”checkbox”,只有选中项的值会被提交(多个value以,连接)

4.对于多个name相同的input type=”radio”,只有选中项的value会被提交(同名的radio只能单选)

5.select的name和被选中的option的vaue(不是option的text)

6.textarea 的name与value

这样被提交的数据可以在提交的页面的后台中以Request.Form[“name”]的方式查到其值

input type=”submit”  “调用”后台方法

知道了form和post的最基本知识,我们就可以模拟ASP.NET的button调用后台方法了,首先准备这样一个页面

<form id="form1" method="post" action="Default.aspx">
        <input type="submit" name="test" value="test"/>
    </form>

在后台添加想调用的方法

protected void test_Click(object sender, EventArgs e)
        {
            Response.Write("Button Click!");
        }

很简单的内容,后台方法的两个参数完全可以不用(和事件有关),填上只是为了增加其逼真性,代码中有几个需要注意的地方

1.form的方法需要设为post,这个很明显。。。

2.form的action设为页面本身,也就是让页面提交给自己

3.input要有name

准备工作做好后就可以模拟JavaScript调用后台方法了,在页面的 OnLoad方法中写入代码

复制代码
protected override void OnLoad(EventArgs e)
        {
            if (Request.Form["test"]!=null)
            {
                test_Click(this, new EventArgs());
            }
            base.OnLoad(e);
          
        }
复制代码

聪明的同学肯定可以看出端倪了,在点击test的时候会提交表单,页面的OnLoad会自动执行,这时候会判断提交过来的表单中是否包含test(submit被点击后会被提交,不点击不提交,所以可以根据name可以判断出哪个按钮被按了),就这么简单,点击submit的时候,预定义的方法就被调用了,要是页面上有很多submit,这时候就需要if-else或者switch或者for这样的东西来判断到底是哪个submit被点击了,然后调用对应方法。

asp: button

对比一下,ASP.NET正好用,首先人家的from是这样的

<form id="form1" runat="server">
</form>

人家自动就给render成这样了

image

我们也不需要自己在OnLoad中添加if-else,只要在control的属性中添加OnClick=”XXX”就可以了,我没看过.NET源码,但是我大胆的揣测,虽然不用再OnLoad里if-else了,但应该也是类似的方式处理。

不自动提交表单的怎么办

细心的同学可能要问了,你这么做是可以,但是依赖于表单提交,我们知道并不是所有的页面元素都会点一下就提交表单,像控件asp: DropDownList的OnSelectIndexChanged事件,人家也会调用回台方法,那是怎么做的?

其实非常简单,对于这种需求,仍然可以用表单提交的方式处理,不能自动提交表单,那么我们可以用JavaScript帮助其提交,看个select change “调用”后台函数的例子,首先像这样修改页面,添加一个select

复制代码
<form id="form1" method="post" action="Default.aspx">
    <input type="hidden" id="__param" name="__param" />
    <input id="test" name="test" type="submit" value="test" />
    <select id="select1" name="select1">
        <option value="0">0</option>
        <option value="1">1</option>
        <option value="2">2</option>
    </select>
    <script type="text/javascript">
        document.getElementById('select1').onchange = function () {
            document.getElementById('__param').value = this.name;
            document.getElementById('form1').submit();
        };
    </script>
    </form>
复制代码

我们除了select元素还添加了两个内容,一个input type=”hidden”的隐藏元素,一段JavaScript脚本,在JavaScript脚本中对select的onchange绑定了一个方法,当select选择项变化的时候,把其name赋值给隐藏域的value,然后提交表单,由于隐藏域可定会被提交,这样我们可以同样在页面的Onload中判断谁的onchange触发了,然后调用预定义方法,后台代码是这样的

复制代码
protected override void OnLoad(EventArgs e)
        {
            string param= Request.Form["__param"];
            if (Request.Form["test"]!=null)
            {
                test_Click(this, new EventArgs());
            }
            else if (param == "select1")
            {
                select_Change(this, new EventArgs());
            }
            base.OnLoad(e);
        }

        protected void test_Click(object sender, EventArgs e)
        {
            Response.Write("Button Click!");
        }

        protected void select_Change(object sender, EventArgs e)
        {
            string newValue = Request.Form["select1"];
            Response.Write("Seclect value chaned to " + newValue);
        }
复制代码

是不是很简单呢?先判断是不是submit,不是的话判断隐藏域,命中后调用预定义方法。

细心的同学仍然会发现问题,要是一个元素上同时又两个事件怎么办?比如还想对这个select添加cilck事件怎么办,这时候我们可以修改隐藏域的值,不仅记录name,还记上事件类型,类似这样

复制代码
document.getElementById('select1').onchange = function () {
            document.getElementById('__param').value = this.name+"$ onchange";
            document.getElementById('form1').submit();
        };

        document.getElementById('select1').onclick = function () {
            document.getElementById('__param').value = this.name+"$ onclick";
            document.getElementById('form1').submit();
        };
复制代码

然后在后台判断的时候,我们可以先把参数按$分割为两个字符串,分别判断元素与事件类型,当然我们也可以再添加一个隐藏域,用来记事件类型,大同小异。

还有同学回问,如果我在客户端同样写了select的onclick,不就把你的代码覆盖了吗?这样我就不能post了,对于这个问题我们大可以换种方式绑定事件处理程序,用addEventListener(attachEven)的方式,这样post的代码和自己写的客户端的就可以同时存在了,这样

复制代码
var select = document.getElementById('select1');
        select.onclick = function () {
            //
            //
            //
        };

        select.addEventListener('clcik', function () {//浏览器兼容性问题要处理,这里就不演示了
            document.getElementById('__param').value = this.name + "$ onclick";
            document.getElementById('form1').submit();
        }, false);
复制代码

 

asp: DropDownList

我们可以看看ASP.NET是怎么处理的,在页面上写一个DropDownList,设起AutoPostBack属性为true

复制代码
<form id="form1" runat="server">
        <asp:DropDownList ID="ddlTest" runat="server" AutoPostBack="true">
        <asp:ListItem>1</asp:ListItem>
        <asp:ListItem>2</asp:ListItem>
        <asp:ListItem>3</asp:ListItem>
    </asp:DropDownList>
    </form>
复制代码

生成的页面源码是这样的

复制代码
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>

</title><style type="text/css"></style></head>
<body cz-shortcut-listen="true">
    <form method="post" action="Default.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="">
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="">
</div>

<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
    theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
//]]>
</script>


<div class="aspNetHidden">

    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAAWUpg6MZl3t8/pBYubwqWOJqSwDGOXu15HYfC2efhAyHc1gIfz8erLrnvHjMLCTGHuRsEl8lEzJ1SVLtM7lgCLfggLVPRtDk70yN7TcfPOwwBRLeEs10HSMSLT9zq5aYmmjMFX5QrdQAuJDrw+EXFTJ">
</div>
        <select name="ddlTest" onchange="javascript:setTimeout('__doPostBack(\'ddlTest\',\'\')', 0)" id="ddlTest">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>

</select>
    </form>


</body></html>
复制代码

 

主要是这个方法,认真读读是不是和我们刚才写的类似呢,人家传了两个隐藏域,一个用来是Target,一个用来及参数

onchange="javascript:setTimeout('__doPostBack(\'ddlTest\',\'\')', 0)"

 

复制代码
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
复制代码

 

未完待续,与君共勉

通过上面例子分析可以看得出来,JavaScript根本没有调用后台函数,只是提交了含有预设参数的表单,服务器根据参数调用后台方法,生成特定HTML,所谓前台调用后台也就这么回事儿。

有一个问题值得思考,为什么这种很想当然的做法PHP程序员可以轻松想到,很多.NET初级程序员却不行,甚至有时候我们都已经在使用了,比如根据Url的QueryString来调用不同方法,或进行不同处理,却没有进一步想到更常用的Button、DropDownList是怎么做到的?还是那句话,.NET程序员当自勉,不要被.NET的易用性惯坏,多学习原理知识,不要过分满足于做出来,而要多追求为什么,这样才能不断进步。


    本文转自魏琼东博客园博客,原文链接:http://www.cnblogs.com/dolphinX/p/3337682.html,如需转载请自行联系原作者

相关文章
|
6月前
|
存储 缓存
.NET 6中Startup.cs文件注入本地缓存策略与服务生命周期管理实践:AddTransient, AddScoped, AddSingleton。
记住,选择正确的服务生命周期并妥善管理它们是至关重要的,因为它们直接影响你的应用程序的性能和行为。就像一个成功的建筑工地,工具箱如果整理得当,工具选择和使用得当,工地的整体效率将会大大提高。
235 0
|
人工智能 开发框架 .NET
如何掌握.NET技术,引领开发前沿:.NET技术的核心能力、在现代开发中的应用实践、以及如何通过.NET技术实现持续创新。
.NET技术已成为软件开发不可或缺的部分,本文分三部分探讨:核心能力如多语言支持、统一运行时环境、丰富的类库及跨平台能力;现代开发实践包括企业级应用、Web与移动开发、云服务及游戏开发;并通过性能优化、容器化、AI集成等方面实现持续创新,使开发者站在技术前沿。
184 3
|
监控 网络安全 调度
Quartz.Net整合NetCore3.1,部署到IIS服务器上后台定时Job不被调度的解决方案
解决Quartz.NET在.NET Core 3.1应用中部署到IIS服务器上不被调度的问题,通常需要综合考虑应用配置、IIS设置、日志分析等多个方面。采用上述策略,结合细致的测试和监控,可以有效地提高定时任务的稳定性和可靠性。在实施任何更改后,务必进行充分的测试,以验证问题是否得到解决,并监控生产环境的表现,确保长期稳定性。
795 1
|
jenkins 测试技术 持续交付
解锁.NET项目高效秘籍:从理论迷雾到实践巅峰,持续集成与自动化测试如何悄然改变游戏规则?
【8月更文挑战第28天】在软件开发领域,持续集成(CI)与自动化测试已成为提升效率和质量的关键工具。尤其在.NET项目中,二者的结合能显著提高开发速度并保证软件稳定性。本文将从理论到实践,详细介绍CI与自动化测试的重要性,并以ASP.NET Core Web API项目为例,演示如何使用Jenkins和NUnit实现自动化构建与测试。每次代码提交后,Jenkins自动触发构建流程,通过编译和运行NUnit测试确保代码质量。这种方式不仅节省了时间,还能快速发现并解决问题,推动.NET项目开发迈向更高水平。
176 8
|
开发框架 缓存 算法
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
810 0
|
Kubernetes 监控 Devops
【独家揭秘】.NET项目中的DevOps实践:从代码提交到生产部署,你不知道的那些事!
【8月更文挑战第28天】.NET 项目中的 DevOps 实践贯穿代码提交到生产部署全流程,涵盖健壮的源代码管理、GitFlow 工作流、持续集成与部署、容器化及监控日志记录。通过 Git、CI/CD 工具、Kubernetes 及日志框架的最佳实践应用,显著提升软件开发效率与质量。本文通过具体示例,助力开发者构建高效可靠的 DevOps 流程,确保项目成功交付。
276 0
|
Cloud Native API C#
.NET云原生应用实践(一):从搭建项目框架结构开始
.NET云原生应用实践(一):从搭建项目框架结构开始
|
人工智能 前端开发 开发工具
NET在企业级应用、Web开发、移动应用、云服务及游戏领域的创新实践
.NET技术自2000年推出以来,在软件开发领域扮演着关键角色。本文从核心优势出发,探讨其统一多语言平台、强大工具集、跨平台能力及丰富生态系统的价值;随后介绍.NET在企业级应用、Web开发、移动应用、云服务及游戏领域的创新实践;最后分析性能优化、容器化、AI集成等方面的挑战与机遇,展望.NET技术的未来发展与潜力。
221 2
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
252 0
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
|
Java Spring UED
Spring框架的异常处理秘籍:打造不败之身的应用!
【8月更文挑战第31天】在软件开发中,异常处理对应用的稳定性和健壮性至关重要。Spring框架提供了一套完善的异常处理机制,包括使用`@ExceptionHandler`注解和配置`@ControllerAdvice`。本文将详细介绍这两种方式,并通过示例代码展示其具体应用。`@ExceptionHandler`可用于控制器类中的方法,处理特定异常;而`@ControllerAdvice`则允许定义全局异常处理器,捕获多个控制器中的异常。
183 0