Есть в мире MS
Windows такой веб-сервер, называется IIS. Для
этого веб-сервера довольно удобно писать
обработчики запросов, используя файлы
типа ashx (generic handler). Несмотря на все усилия
Микрософт, для написания таких обработчиков
нет необходимости в Visual Studio. Хотя .Net
используется, куда ж без него.
Типичный файл
(load.ashx) выглядит примерно так:
<%@ WebHandler Language="C#" Class="load" Debug="true" %> using System; using System.IO; using System.Web; using System.Collections.Generic; using System.Text; using System.Xml.Serialization; using System.Web.Caching; public class load: IHttpHandler { // Override the ProcessRequest method. public void ProcessRequest(HttpContext context) { var saveid = String.Empty; // only for GET method saveid = context.Request.QueryString["map"]; var path = VUtils.storeconfFromJson( VUtils.loadConfig( VUtils.storageConfigFilename(context)) ).fileStoragePath; var fname = String.Format(@"{1}/map.{0}.js", saveid, path); context.Response.ContentType = "application/json"; context.Response.ContentEncoding = Encoding.UTF8; context.Response.Write(string.Format("{{file: '{0}'}}", fname)); } // Override the IsReusable property. public bool IsReusable { get { return false; } } }
Из этого файла, для краткости, вырезан
вспомогательный код, в частности класса
«VUtils».
И вот тут я
подхожу к главному. Как бы сделать так,
чтобы повторно используемый код вынести
в отдельный файл?
Хочу аналог
директивы «include», как в C/C++.
Ответ неожиданно
прост, хотя в интернетах и не находится:
используй «CompilerOptions», Люк.
Пример. Выношу
библиотеку кода в отдельный файл lib.cs:
using System; using System.IO; using System.Web; using System.Collections.Generic; using System.Text; using System.Xml.Serialization; using System.Web.Caching; public class VUtils { public class VStoreConfig { public string fileStoragePath { get; set; } } public static string computeSHA1Hash(string val) { if(val.Equals("")) { return ""; } byte[] data = System.Text.Encoding.UTF8.GetBytes(val); System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1Managed(); byte[] res = sha.ComputeHash(data); return System.BitConverter.ToString(res).Replace("-", "").ToUpper(); } public static string storageConfigFilename(HttpContext context) { return context.Server.MapPath("~/store.config"); } private static object _lockobject = new object(); public static string loadConfig(string fileName) { string config = string.Empty; lock(_lockobject) { if(System.IO.File.Exists(fileName)) { using(System.IO.StreamReader file = new System.IO.StreamReader(fileName)) { config = file.ReadToEnd(); } } } return config; } public static VStoreConfig storeconfFromJson(string confJson) { var jss = new System.Web.Script.Serialization.JavaScriptSerializer(); var cnf = jss.Deserialize<VStoreConfig>(confJson); return cnf; } }
В обработчике
запроса load.ashx меняю заголовок:
<%@ WebHandler Language="C#" Class="load" Debug="true" CodeBehind="lib.cs" CompilerOptions="c:\Inetpub\wwwroot\miniportal\store\lib.cs" %> ... public class load: IHttpHandler { ... var path = VUtils.storeconfFromJson( VUtils.loadConfig( VUtils.storageConfigFilename(context)) ).fileStoragePath; ...
И этого достаточно. В коде класса «load»
я могу пользоваться классами из библиотеки
lib.cs.
Для завершения
картины, вот полный код другого
обработчика, save.ashx:
<%@ WebHandler Language="C#" Class="store" Debug="true" CodeBehind="lib.cs" CompilerOptions="c:\Inetpub\wwwroot\miniportal\store\lib.cs" %> using System; using System.IO; using System.Web; using System.Collections.Generic; using System.Text; using System.Xml.Serialization; using System.Web.Caching; public class store: IHttpHandler { // Override the ProcessRequest method. public void ProcessRequest(HttpContext context) { var jsonString = String.Empty; // only for POST method jsonString = context.Request.Form["map"]; if(jsonString == null) { jsonString = ""; } var hash = VUtils.computeSHA1Hash(jsonString); var path = VUtils.storeconfFromJson( VUtils.loadConfig( VUtils.storageConfigFilename(context)) ).fileStoragePath; var fname = String.Format(@"{1}/map.{0}.js", hash, path); System.IO.File.WriteAllText(fname, jsonString); context.Response.ContentType = "application/json"; context.Response.ContentEncoding = Encoding.UTF8; context.Response.Write(string.Format("{{sha1: '{0}'}}", hash)); } // Override the IsReusable property. public bool IsReusable { get { return false; } } }
Задача решена, принцип DRY не нарушен.
Пока неясно,
как избавиться от указания полного пути
к файлам в директиве CompilerOptions. Но пока
это не сильно мешает.
original post http://vasnake.blogspot.com/2013/10/ashx-include.html
Комментариев нет:
Отправить комментарий