ASP.NET 高级泛型处理程序 ASHX
将您的泛型处理程序提升到一个新的水平...
GitHub 仓库现已可用
我也会在 CP 上更新项目进度,但现在您也可以在 GitHub 上 fork 它
简介
在 ASP.NET 中,我们有一个通常被忽略的功能,称为泛型处理程序。我看到很多人使用页面来处理 AJAX 请求,而我们可以使用这种成本低得多的终结点。这是一个完全实现的泛型处理程序,它真正知道如何处理您的 http(AJAX 和非 AJAX)请求。
背景
长期以来,我一直使用普通的泛型处理程序(ASHX 文件)来处理我的 AJAX 请求,但这感觉很愚蠢且痛苦。我的意思是,功能是有的,但处理请求的整个过程并不直接。所以我列出了我想要的东西,现在它已经远不止这些了。
- 最新版本 v2.5!
- 完全支持将集合作为请求参数
- 完全支持嵌套集合
- 支持原生和复杂项类型
- 改进了对复杂类型作为方法参数的支持
- 改进的 HTTP 动词过滤器
- 新的 HTTP 动词过滤器属性(DELETE 和 PUT)
- 改进的控制器帮助(更多功能即将推出)
- 改进的性能(仍在努力进一步提高)
- 性能改进一直在进行中。根据我的简单测试,这个控制器已经达到了与 ASP.NET MVC 控制器相同的性能水平。
- 主演示项目中添加了新的 PerformanceTest.aspx
- 创建了新的 ASP.NET MVC 项目,用于与 MVC 控制器进行性能比较
- 此项目未添加到解决方案中。如果您想使用,请添加。
- 小的重构和改进
- 最新版本 v2.0!
- OnMethodInvoke 和 AfterMethodInvoke 虚方法
- 这些允许在方法调用之前和之后介入执行
- public void SetResponseContentType(ResponseContentTypes value)
- 从枚举设置响应内容类型的简便方法
- 按处理程序和按方法指定支持的 HTTP 动词
- 现在我们可以通过简单地用相关属性装饰方法来指定一个方法是否只支持某些 HTTP 动词
- 主要 HTTP 动词(GET、POST、PUT 和 DELETE)的默认方法
- 如果没有传递方法,处理程序将调用与请求 HTTP 动词相关的方法。
- 这些方法可以被覆盖以实现您的逻辑。
- 响应序列化改进(JSON 和 XML)
- 您现在可以使用请求中的 `returntype` 参数来指定您想要的响应数据格式,而无需修改您的代码。
- 默认是 JSON,但您也可以传递 XML 或 HTML。
- 可以在方法范围内禁用默认序列化。
- 性能优化
- v1.1
- 支持将复杂对象作为方法参数
- 现在您可以将自定义类放在处理程序方法的参数中。
- 自动填充类及其所有嵌套类型!!
- v1.0
- 解析查询字符串的标准方法
- 透明处理同一处理程序中的多个方法
- 支持具有多个类型化参数的方法,而不仅仅是字符串
- 支持接收列表作为参数的方法
- 支持传递比方法预期参数少的情况(例如可选参数)
- 透明地处理 POST 或 GET 请求
- 支持默认对象序列化为 JSON,但仍然允许我在每个方法中覆盖它
- 默认返回 application/json,但仍然允许我在每个方法中覆盖它
- 支持 jQuery
$.ajax
请求 - 支持通过查询字符串进行请求(直接在浏览器中输入 URL)
- 一种可视化处理程序支持的方法(类似 Web 服务)
- 可扩展
使用代码
我正在努力改进此文档。
在此之前,您需要知道的所有信息都在演示项目的 Default.aspx 中。
列出处理程序的方法
我提供了一种非常基本的方法来列出处理程序公开的方法。这对于测试处理程序是否正常工作(例如 Web 服务)特别有用。要做到这一点,只需在处理程序 URL 的末尾附加 `?help` 即可。
https:///mydemohandler.ashx?help
通过浏览器 URL 调用处理程序
使用这些处理程序非常简单
- 创建一个新的泛型处理程序
- 清除处理程序类内的所有内容
- 继承我的处理程序类
- 完成!现在您只需要添加您的方法。
让我们创建一个非常简单的示例,该示例接收一个姓名并返回一个字符串(请参见项目)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using App.Utilities.Web.Handlers;
namespace CodeProject.GenericHandler
{
public class MyFirstHandler : BaseHandler
{
// I don't bother specifying the return type, it'll be serialized anyway
public object GreetMe(string name)
{
return string.Format("Hello {0}!", name);
}
}
}
要通过 URL 调用此方法,请使用
MyFirstHandler.ashx?method=GreetMe&name=AlexCode
使用 jQuery 的 AJAX 请求
如果您想使用 jQuery AJAX 方法,您只需要知道处理程序期望接收的对象。在 `$.ajax` 请求的 `data` 属性中,您必须传递类似以下内容:
{ method: 'The method you want to call', args: { the arguments to pass } }请注意,一切都区分大小写!
$.ajax({ url: 'MyFirstHandler.ashx', type: 'GET', data: { method: 'GreetMe', args: { name: 'AlexCode'} }, success: function (data) { alert(data); } });
编写返回 HTML 的方法
正如我在上面的意向点中提到的,我需要一些方法来返回任何我想要的内容,如 HTML、XML、图像、文件等。处理程序的默认行为是返回 JSON,因此,按方法,我们需要明确表示我们希望以自己的方式处理事物。为此,只需在方法内的任何位置使用这些行:
SkipContentTypeEvaluation = true; SkipDefaultSerialization = true; // you can specify the response content type as follows context.Response.ContentType = "text/html";让我们看看如何编写一个返回 HTML 的处理程序方法。
public object GiveMeSomeHTML(string text) { StringBuilder sb = new StringBuilder(); sb.Append("<head><title>My Handler!</title></head>"); sb.Append("<body>"); sb.Append(" This is a HTML page returned from the Handler "); sb.Append(" The text passed was: " + text + " "); sb.Append("</body>"); context.Response.ContentType = "text/html"; SkipContentTypeEvaluation = true; SkipDefaultSerialization = true; return sb.ToString(); }
可选参数和可空类型
方法中的所有参数都是可选的。如果未传递,则为其分配默认值。所有参数也都可以是可空的。在这种情况下,默认值将为 `null`。
对复杂类型的支持
假设您有一个 JSON 对象和一个服务器端的类与之映射。在服务器端填充这个类很麻烦。通常,我们会将每个属性作为 Handler 方法的参数传递,实例化该类的一个新实例,然后逐个设置属性……很麻烦,对吧?现在不再是了!这个 Handler 现在支持自动类实例创建和属性设置。我称之为对象填充! " /> 而且还有更多!如果这个类有也暴露其他自定义类的属性,它们也会被填充!!请确保所有类都有公共的默认构造函数
// Now you can have method like this public object SendPersonData(Person person) { return person.Name; } // your ajax call object would be something like ... data: { method: 'SendPersonData', args:{ person: { Name: 'Alex' } } } ...
请参阅随附的代码示例以获取更多示例。
关注点
我可以肯定地说,这个 Handler 已经为我节省了大量开发和维护时间。目前,我所有的 AJAX 请求都指向类似这样的 Handler 中的一个方法。
历史
- v2.5 - 备受期待的集合支持来了!完整详情请见上文!
- v2.0 - 新功能和性能增强
- v1.1 - 添加了对复杂参数的支持
- v1.0 - 第一个公开版本
- 这是一个进行中的项目,我会定期改进它。
我毫不怀疑您会尝试在我想象不到的场景中使用它。请将您的请求和愿望发送给我,我将尽力实现它们。