이번에는 경량 Ajax 컴포넌트 작성 방법을 알려드리겠습니다(자세한 설명은 그림과 텍스트로 설명). 경량 Ajax 컴포넌트 작성 시 주의사항은 무엇인가요?
이전 소개를 통해 페이지 객체의 메소드를 실행하기 위한 핵심은 요청에서 매개변수를 얻고 지정된 메소드를 실행하는 프로세스인 리플렉션이라는 것을 알았습니다. 실제로 이는 ASP.NET MVC 프레임워크의 핵심 아이디어와 매우 유사합니다. URL을 구문 분석하고 여기에서 컨트롤러와 작업 이름을 가져온 다음 컨트롤러 개체를 활성화하고 요청에서 작업 매개변수를 가져옵니다. 작업을 실행합니다. 웹 양식 플랫폼에서는 .aspx.cs에 메서드를 작성합니다. 우리가 달성하려는 것은 페이지 개체가 생성되기 전에 지정된 메서드를 실행한 다음 결과를 반환하는 것입니다.
먼저 구현 후 몇 가지 호출 예를 살펴보겠습니다. 이러한 함수는 조합하여 사용할 수도 있습니다.
[AjaxMethod]
public void Test1(int index)
{
//简单调用
}
[AjaxMethod]
public string Test2(Test test)
{
return "参数为一个Test实例";
}
[AjaxMethod(OutputCache = 20)]
public string Test3(int index)
{
return "输出结果缓存20秒";
}
[AjaxMethod(ServerCache = 20)]
public string Test4()
{
return "在服务端缓存20秒";
}
[AjaxMethod(SessionState=SessionState.None)]
public void Test5()
{
//Session未被加载
}
[AjaxMethod(SessionState = SessionState.ReadOnly)]
public void Test6()
{
//Session只能读不能写
}
[AjaxMethod(SessionState = SessionState.ReadWrite)]
public void Test7()
{
//Session可以读写
}
[AjaxMethod(IsAsync = true)]
public void Test8()
{
//异步调用
}
로그인 후 복사
우리는 이미 기본 실행 프로세스를 숙지했으며 이제 바로 주제로 이동합니다.
Ajax 규칙
일반적으로 주류 브라우저가 ajax를 사용하여 비동기 요청을 보내는 경우 요청 헤더에는 X-Requested-With:XMLHttpRequest 표시가 포함됩니다. 이 태그를 직접 사용하여 Ajax 요청인지 확인할 수도 있지만 프로젝트에서 다른 구성요소가 서로 영향을 주지 않도록 사용자 정의 요청 헤더를 추가합니다.
internal static class AjaxConfig
{
/// <summary>
/// 请求头Ajax标记键
/// </summary>
public const string Key = "AjaxFlag";
/// <summary>
/// 请求头Ajax标记值
/// </summary>
public const string Value = "XHR";
/// <summary>
/// 请求头Ajax方法标记
/// </summary>
public const string MethodName = "";
}
로그인 후 복사
http 요청 헤더에 AjaxFlag: XHR이 포함되어 있으면 그것이 우리가 처리하려는 것임을 의미합니다. 또한 http 헤더의 MethodName은 실행하려는 메소드의 이름을 나타냅니다.
AjaxMethodAttribute 마크 속성
마크 속성은 반사에 사용됩니다. 여기서는 필요한 몇 가지 기능을 정의합니다. 우리는 다음을 희망합니다:
1. 세션 상태 구성 가능
2. 비동기 핸들러 지원
3. 캐시 가져오기 지원
4. 서버 측 캐시 지원
정의는 다음과 같으며 태그는 AttributeUsag로 표시됩니다. 메소드에만 사용할 수 있습니다.
/// <summary>
/// ajax方法标记属性
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class AjaxMethodAttribute : Attribute
{
public AjaxMethodAttribute()
{
}
private SessionState _sessionState = SessionState.None;
private int _outputCache = 0;
private int _serverCache = 0;
private ContentType _contentType = ContentType.Plain;
private bool _isUseAsync = false;
/// <summary>
/// session状态
/// </summary>
public SessionState SessionState
{
get { return _sessionState; }
set { _sessionState = value; }
}
/// <summary>
/// 客户端缓存时间,以秒为单位。该标记只对get请求有效
/// </summary>
public int OutputCache
{
get { return _outputCache; }
set { _outputCache = value; }
}
/// <summary>
/// 服务端缓存时间,以秒为单位
/// </summary>
public int ServerCache
{
get { return _serverCache; }
set { _serverCache = value; }
}
/// <summary>
/// 输出类型(默认为text/plain)
/// </summary>
public ContentType ContentType
{
get { return _contentType; }
set { _contentType = value; }
}
/// <summary>
/// 使用启用异步处理
/// </summary>
public bool IsAsync
{
get { return _isUseAsync; }
set { _isUseAsync = value; }
}
}
/// <summary>
/// Session状态
/// </summary>
public enum SessionState
{
None,
ReadOnly,
ReadWrite
}
/// <summary>
/// 输出内容类型
/// </summary>
public enum ContentType
{
Plain,
Html,
XML,
Javascript,
JSON
}
로그인 후 복사
다양한 핸들러와 AjaxHandlerFactory
이전 기사에 따르면 특정 핸들러는 주로 비동기식과 비동기식의 두 가지 범주로 나뉘며 이 두 가지 범주에는 세 가지 유형의 세션 상태만 지원됩니다. 읽기(IReadOnlySessionState 인터페이스 구현) 및 읽기 및 쓰기(IRequiresSessionState 인터페이스 구현). IReadOnlySessionState 및 IRequiresSessionState는 단지 표시 인터페이스일 뿐입니다(메서드가 없으면 표시 특성을 사용하여 구현하는 것이 더 합리적입니다). 비동기 처리기는 IHttpAsyncHandler 인터페이스를 구현해야 하며, 이 인터페이스는 IHttpHandler를 구현합니다. Handler의 ProcessRequest 메서드(또는 BeginProcessRequest)는 메서드를 실행하려는 곳입니다. 정의는 다음과 같습니다.
비동기 상태의 핸들러:
//不支持Session
internal class SyncAjaxHandler : IHttpHandler
{
private Page _page;
private CacheMethodInfo _cacheMethodInfo;
internal SyncAjaxHandler(Page page, CacheMethodInfo cacheMethodInfo)
{
_page = page;
_cacheMethodInfo = cacheMethodInfo;
}
public void ProcessRequest(HttpContext context)
{
//执行方法(下面详细介绍)
Executor.Execute(_page, context, _cacheMethodInfo);
}
public bool IsReusable
{
get { return false; }
}
public static SyncAjaxHandler CreateHandler(Page page, CacheMethodInfo cacheMethodInfo, SessionState state)
{
switch (state)
{
case SessionState.ReadOnly:
return new SyncAjaxSessionReadOnlyHandler(page, cacheMethodInfo);
case SessionState.ReadWrite:
return new SyncAjaxSessionHandler(page, cacheMethodInfo);
default:
return new SyncAjaxHandler(page, cacheMethodInfo);
}
}
}
//支持只读Session
internal class SyncAjaxSessionReadOnlyHandler : SyncAjaxHandler, IReadOnlySessionState
{
internal SyncAjaxSessionReadOnlyHandler(Page page, CacheMethodInfo cacheMethodInfo)
: base(page, cacheMethodInfo)
{
}
}
//支持读写Session
internal class SyncAjaxSessionHandler : SyncAjaxHandler, IRequiresSessionState
{
internal SyncAjaxSessionHandler(Page page, CacheMethodInfo cacheMethodInfo)
: base(page, cacheMethodInfo)
{
}
}
로그인 후 복사
비동기 상태의 핸들러:
//不支持Session
internal class ASyncAjaxHandler : IHttpAsyncHandler, IHttpHandler
{
private Page _page;
private CacheMethodInfo _cacheMethodInfo;
internal ASyncAjaxHandler(Page page, CacheMethodInfo cacheMethodInfo)
{
_page = page;
_cacheMethodInfo = cacheMethodInfo;
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
//执行方法(下面详细介绍)
Action<Page, HttpContext, CacheMethodInfo> action = new Action<Page, HttpContext, CacheMethodInfo>(Executor.Execute);
IAsyncResult result = action.BeginInvoke(_page, context, _cacheMethodInfo, cb, action);
return result;
}
public void EndProcessRequest(IAsyncResult result)
{
Action<Page, HttpContext, CacheMethodInfo> action = result.AsyncState as Action<Page, HttpContext, CacheMethodInfo>;
action.EndInvoke(result);
}
public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
public bool IsReusable
{
get { return false; }
}
public static ASyncAjaxHandler CreateHandler(Page page, CacheMethodInfo cacheMethodInfo, SessionState state)
{
switch (state)
{
case SessionState.ReadOnly:
return new ASyncAjaxSessionReadOnlyHandler(page, cacheMethodInfo);
case SessionState.ReadWrite:
return new ASyncAjaxSessionHandler(page, cacheMethodInfo);
default:
return new ASyncAjaxHandler(page, cacheMethodInfo);
}
}
}
//支持只读Session
internal class ASyncAjaxSessionReadOnlyHandler : ASyncAjaxHandler, IReadOnlySessionState
{
internal ASyncAjaxSessionReadOnlyHandler(Page page, CacheMethodInfo cacheMethodInfo)
: base(page, cacheMethodInfo)
{
}
}
//支持读写Session
internal class ASyncAjaxSessionHandler : ASyncAjaxHandler, IRequiresSessionState
{
internal ASyncAjaxSessionHandler(Page page, CacheMethodInfo cacheMethodInfo)
: base(page, cacheMethodInfo)
{
}
}
로그인 후 복사
AjaxHandlerFactory는 요청에 따라 특정 핸들러를 생성하는 데 사용되는 IHandlerFactory 인터페이스를 구현합니다. .config. AjaxHandlerFactory의 GetHandler는 요청을 가로채는 첫 번째 단계입니다. 요청 헤더에 있는 AjaxFlag:XHR을 사용하여 처리해야 하는지 여부를 결정합니다. 그렇다면 핸들러를 생성하고, 그렇지 않으면 일반적인 방법으로 진행합니다. 메서드가 .aspx.cs에 작성되었으므로 요청은 페이지(페이지, IHttpHandler 구현) 유형인 .aspx 접미사로 되어 있습니다. 페이지는 IHandlerFactory 인터페이스도 구현하는 PageHandlerFactory를 통해 생성됩니다. 핸들러를 생성합니다. 따라서 IHttpHandler를 생성하려면 PageHandlerFactory를 사용해야 하지만 PageHandlerFactory의 constructor는 보호된 내부 유형이므로 새 항목을 직접 생성할 수 없으므로 CommonPageHandlerFactory를 통해 상속해야 합니다.
PageHandlerFactory를 통해 페이지를 얻은 후 메소드 이름과 결합하면 리플렉션을 통해 AjaxMethodAttribute 마크 속성을 얻을 수 있습니다. 그런 다음 관련 속성을 기반으로 특정 처리기를 생성합니다. 구체적인 코드는 다음과 같습니다: