Есть в мире 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
Комментариев нет:
Отправить комментарий