Translate

пятница, 14 сентября 2012 г.

Немного о форматировании при преобразовании html в excel

Тексты пересказывать не буду. Их много. Просто приведу подборку ссылок.

http://niallodoherty.com/post.cfm/basic-html-to-excel-formatting
http://www.agoric.com/sources/software/htmltoExcel
http://forums.majorgeeks.com/showthread.php?t=257899
http://forums.iis.net/t/1156329.aspx

вторник, 11 сентября 2012 г.

Dynamic OrderBy в Linq

Частая задача при работе с наборами данных Linq - сортировка по полю заданному из строкового параметра (например GridView onSorting).

Конечно, можно сделать простую конструкцию типа case:

switch(param) {
case 'Field1':  return table.OrderBy(t=>t.Field1);
case 'Field2':  return table.OrderBy(t=>t.Field2);
case 'Field3':  return table.OrderBy(t=>t.Field3);
}

и это будет выходом в частной задаче, но сегодня мне потребовалось решить данный вопрос для нескольких различных мест... Шаблон общий, а код разный... да еще и в поддержке не простой... (структура данных изменчива).

На помощь пришла статья с stackoverflow: http://stackoverflow.com/questions/41244/dynamic-linq-orderby

Далее краткий snippet кода:

public static class DynamicSortHelper
    {
        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "OrderBy");
        }
        public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "OrderByDescending");
        }
        public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "ThenBy");
        }
        public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
        {
            return ApplyOrder<T>(source, property, "ThenByDescending");
        }
        static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
        {
            string[] props = property.Split('.');
            Type type = typeof(T);
            ParameterExpression arg = Expression.Parameter(type, "x");
            Expression expr = arg;
            foreach (string prop in props)
            {
                // use reflection (not ComponentModel) to mirror LINQ
                PropertyInfo pi = type.GetProperty(prop);
                expr = Expression.Property(expr, pi);
                type = pi.PropertyType;
            }
            Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
            LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

            object result = typeof(Queryable).GetMethods().Single(
                    method => method.Name == methodName
                            && method.IsGenericMethodDefinition
                            && method.GetGenericArguments().Length == 2
                            && method.GetParameters().Length == 2)
                    .MakeGenericMethod(typeof(T), type)
                    .Invoke(null, new object[] { source, lambda });
            return (IOrderedQueryable<T>)result;
        }
    }

четверг, 16 августа 2012 г.

Немного о проблеме "Все соединения заняты" в Remote Desktop Connection

Для многих, кто имеет отношения к серверам windows в корпоративном окружении, проблема знакома. Причина - неудобно сделанная процедура окончания сессии. Вместо того, чтобы сделать "Пуск"-"Выход из системы" проще нажать на крестик наверху. Так делают многие и я не исключение.

Что же делать, если ваши коллеги накануне заняли все доступные соединения, а на сервер кровь из носу надо:

Универсальный способ - воспользоваться ключем /admin

В командной строке набираем mstsc.exe /admin (mstsc.exe /console для подключения к Windows 2000 (если у кого он еще живет)). 

Эта команда позволит подключиться в обход квоты при условии, что вы являетесь администратором на данном сервере.

Далее через вкладку Users в Task Manager можно отключить от сервера забывчивых коллег и войти уже нормальным способом.

вторник, 7 августа 2012 г.

Немного о Warm up

В любом web-приложении наступает этап, когда функциональные требования закрыты, профайлер отложен в сторону, т.к. все уже приемлемо "летает" на dev, код ушел на тестовые окружения, но... при первом запуске все сильно тормозит...

Далее все летает, но первый запуск... Подобная проблема есть в большинстве возможных платформ... Для ряда платформ есть более эффективные методики. Для reverse proxy, например, это использование key-value базы с предпубликованным контентом как источника данных,
Для IIS 7.5 это autostart module или магическая фича autostart ASP.NET 4 (эффект которой я немного не заметил).

Общее решение здесь - запланированная задача, которая вызывает наиболее важные ссылки раз в заданный период и тонкая настройка периодов реинициализиции приложений.

Как это автоматизировать? Просто.

Существуют простые утилиты, такие как curl, которые позволяют из командной строки "дернуть" интересующие ссылки и таким образом инициализировать кэши заново.

Период запуска запланированной задачи сильно зависит от настроек платформы и варьируется от раз в 5 минут, до раз в день.


четверг, 26 июля 2012 г.

jQuery Mobile анимация загрузки при переходе на внешнюю ссылку

Сегодня потребовалось решить небольшую задачку касательно индикации загрузки при переходе по внешней ссылке или postback.

В нашем приложении есть несколько операций, которые могут спокойно выполняться 5-15 секунд и это нормально. Поскольку это ASP.NET, то как я писал раньше, все ссылки на страницы с применением postback должны быть аннотированы data-ajax="false".

К моему разочарованию jQuery Mobile не выводит никакой индикации при переходе на внешнюю ссылку, аргументируя это невозможностью организовать полную анимацию перехода...

Данному заявлению я поверил частично, т.к. в yotaplay.ru сам решал подобную задачу. Организовать полный цикл анимации нельзя по двум причинам:

  • броузеро/платформенно-зависимые тормоза и глюки при загрузке и парсинге новой страницы. (победить можно, но ооочень сложно и нестабильно от железа и версий)
  • невозможность корректного ответа в общем случае на принимающей странице
Но это мне и не нужно в общем-то. Мне нужно показать, что после нажатия кнопки мы думаем 5-10 секунд. 

Немного порывшись в исходниках jQuery Mobile нашел метод рисующий"крутилку". Мне большего и не надо.

Далее 5 строк кода - решение маленькой, но очень не документированной проблемки:

$(document).ready(function () {
            $(window).bind('beforeunload', function () {
                $.mobile.showPageLoadingMsg();
            });
        });

Как это работает:

Перед переходом броузер вызывает onBeforeUnload, в котором мы запускаем анимацию ожидания из JQM.

Загрузившись новая страница моментально перетирает старую и создается первое приближение адекватного перехода.

Особенность: В IE бегунок не бегает - это известная проблема IE. В моем случае самого факта наличия бегунка хватает. Есть способы решения через JS, но это вне рамок данной заметки.

вторник, 24 июля 2012 г.

легкий переносимый web-сервер для автономного запуска ASP.NET приложений

Для чего нужны подобные проекты?

Во-первых - для отладки,
Во-вторых - в случае когда вам хочется запустить web-приложение на отдельно взятом компьютере при этом не привязываться сильно к установленным и настроенным компонентам, таким как IIS. Такая вещь, например, используется в MS Outlook,MS Project для организации работы offline компонентов приложений интеграции.

В этой статье нет кода, хотя подобный сервер в простом случае пишется за 1-2 дня посредством использования http.sys, но зачем писать, когда все уже придумано?

Итак...

Первым из этой серии идет cassini или более правильно ASP.NET Development Web Server. Хорошее описание данного сервера лежит, например здесь: http://www.ironspeed.com/Designer/6.2.1/WebHelp/Part_V/The_ASP_NET_Development_Server.htm

Данный сервер изначально был создан для .NET 1.1. Позднее вошел в состав VS 2005 и там и прижился.

Важным моментом, ограничивающим его использование является отсутствие возможности принимать запросы из внешней сети.


С этого и начался мой очередной поиск альтернатив сегодня... Много он не занял, благо исходники когда-то были опубликованы в сеть и клонов достаточно.

В итоге остановился на http://cassinidev.codeplex.com/ В нем можно задавать виртуальные директории, hostname, time-out запроса, адреса по которым отвечать на запросы, порт на котором отвечает сервер.

Возможна работа как через GUI, командную строку, API .NET (поставляется в виде nuget пакета).


пятница, 20 июля 2012 г.

Очистка кэша nginx через HTTP

Сегодня мы продолжаем строить кэширующий прокси. Речь пойдет про очистку кэша посредством http вызова.

В предыдущей записи мы определились, что для работы скриптов у нас на произвольном сервере nginx развернуто MONO через fastcgi.

Для очистки кэша есть простой и достаточно эффективный протокол ssh. SharpSSH меня более чем устроил. 


Создал пустой ASP.NET проект, в котором описал HTTPHandler

public bool IsReusable { get { return false; }  }

public void ProcessRequest(HttpContext context) {
            context.Response.Buffer = false;
            var exec = new SshExec(ConfigurationManager.AppSettings["Host"], ConfigurationManager.AppSettings["User"]);            
           exec.Password= ConfigurationManager.AppSettings["Password"] ;
            context.Response.Write("Connecting...");
            exec.Connect();
            context.Response.Write("OK\n");
            context.Response.Write("Cleaning cache...");
            var output = exec.RunCommand("rm -R /var/nginx/cache/*");
            context.Response.Write("DONE\n" + output + '\n');
            context.Response.Write("Disconnecting...");
            exec.Close();
            context.Response.Write("OK");
            context.Response.End();
        }
Прописываем в web.config handler и параметры
<add verb="*" path="*" type="RSP2.CacheClean.CleanCacheHandler" />

<add key ="Host" value="localhost"/>
<add key ="User" value="abc"/>
<add key ="Password" value="123456"/>

Добавляем сборки SharpSSH.dll, DiffieHellman.dll и Org.Mentalis.Security.dll из SharpSSH


и проверяем работу скрипта в том числе и на сервере.

Немного о безопасности и эффективности

Данный скрипт является рабочим прототипом. В реальности нужно не забыть снять данному пользователю доступ ко всему кроме каталога-кэша nginx. 

В идеале нужно реализовать защиту от подключения по ssh из внешней сети (я надеюсь вы будете по internal network между серверами общаться).

Ну и очистка полного кэша nginx, как сделано в этом примере в реальным решением может быть только в первом приближении.


P.S.: Нашел ветку, где такой же подход сделан в приложении на PHP
http://wordpress.org/support/topic/plugin-nginx-manager-purge-cache-on-10-proxies

https://github.com/perusio/nginx-cache-purge/blob/master/nginx-cache-purge можно использовать для прицельной очистки кэша