суббота, 15 октября 2011 г.

Баг qip

Вчера написал в службу поддержки qip'a следующее сообщение:
"Невозможно кинуть контакт в окно сообщений (тем самым создав чат), если этот контакт присутствует на рабочем столе (плавающий)".


На что получил ответ:

вторник, 11 октября 2011 г.

Удаленное скачивание торрентов

Некоторое время мучался мечтою удалённой закачки торрентов.
Идёшь себе по парку и думаешь: "А вот неплохо бы такое и такое кино посмотреть". Достаешь мобилку, раз-два-клик и дома запускается закачка. А как приходишь, уже и готово все.
Вот недавно придумали изящное решение этой проблемы =)

понедельник, 3 октября 2011 г.

Java vs. C#, Round 1

Да, я очень предвзято отношусь к указанным технологиям, так что далее всё надо понимать как моё личное имхо. Я не собираюсь сравнивать тут тонкости работы GC, организацию кучи, Sql Server и oracle, кроссплатформенность, "3 billion devices around the world", win phone 7 и прочее. Только code style. "Это всё несущественно!" — чтож, пожалуйста, не читайте, вы мне не должны.

Просто личное впечатление от процесса разработки.
Добро пожаловать под кат, раунд 1.

пятница, 30 сентября 2011 г.

Cтрого типизированный аналог для UrlHelper.Action(string, string)

Пришло в голову написать строго типизированный аналог для UrlHelper.Action(string, string):
public static class MyMvcExtensions
{
  public static string Action<TController>(this UrlHelper urlHelper,
      Expression<Func<TControllerActionResult>> action)
    where TController : Controller
  {
    var controllerName = typeof (TController).Name;
    var actionName = GetActionName(action);
    return urlHelper.Action(actionNamecontrollerName);
  }

  private static string GetActionName<TController>(
      Expression<Func<TControllerActionResult>> action)
    where TController : Controller
  {
    var mce = action.Body as MethodCallExpression;
    if (mce == null)
    {
      throw new InvalidOperationException(action.Name + " is not a valid controller action");
    }
    return mce.Method.Name;
  }
}

Использовать так:
<a href="@(Url.Action<HomeController>(c => c.About()))">about</a>
<a href="@(Url.Action<HomeController>(c => c.Index()))">index</a>

Идея ясна, вроде, придумать дельше легко. Может кому и пригодится =)
В любом случае я советую сделать просто статический класс, расширающий UrlHelper и в котором хранить все-все ссылки в стандартном формате, которые используете в проекте, и обращаться только к нему.

понедельник, 19 сентября 2011 г.

Немного о Chrome Extensions

Не так давно, когда я ещё не знал что есть кнопочка "Сохранить" в Клавогонках при создании игры, меня очень парило постоянное ручное выставление режима в "Одиночный, 5 секунд". Подумалось тогда, что можно написать расширение для хрома, которое будет делать это за меня.
Собственно, на это и был потрачен вчерашний вечер.

среда, 7 сентября 2011 г.

Почему я сменил работу

Я сменил работу не потому что был чем-то недоволен. Даже наоборот, предыдущая работа меня полностью устраивала. Но, тем не менее — лучшее враг хорошего. Да и никто не сказал что на новом месте будет лучше, есть только догадки.

вторник, 6 сентября 2011 г.

Использование выражений для устранения дублирования кода

Последнее время стал заниматься такой фигнёй для устранения дублирования. Да, возможно, это бред.

Что здесь происходит?
1. Из репозитория берётся метод, использующий постраничный вывод данных.
2. Этот метод передаётся в метод, который инкапсулирует логику работы со страницами.
3. Всё это оборачивается в using unit of work'а (uow = Unit of work), в котором создается Entity контекст.
4. Возвращается в дочернем экшене.
Это похоже на ASP.NET WebForms Control (.ascx)


[ChildActionOnly]
public PartialViewResult GetExclusiveVideo(int count, int page = 1)
{
       return InUow(() => PartialView(Paged(_videoItemRepository.ExclusiveVideos
                                            page, count)));
}

private TModel InUow<TModel>(Func<TModel> func)
{
       using (_unitOfWorkFactory.Create())
       {
             return func();
       }
}

private TModel InUow<TModel>(Func<IUnitOfWork, TModel> func)
{
       using (var uow = _unitOfWorkFactory.Create())
       {
             return func(uow);
       }
}
  
private IEnumerable<TModel> Paged<TModel>(Func<int, int, IEnumerable<TModel>> pagedMethod,                      
                                          int page, int count)
{
       var skip = (page - 1)*count;
       return pagedMethod(skip, count);
}

Красиво? Удобно? Неясно? Слишком обще? Есть ещё извращённые идеи?
Спасибо за внимание.

воскресенье, 4 сентября 2011 г.

Музыка

Решил завязать с музыкой.
Почему?
Не знаю чего конкретно не хватает: времени, упорства, воображения, лицензионного софта?
Очень быстро портится настроение и парят вопросы "Есть что нового послушать?". Нету.
Надо сосредоточиться на чём-то одном. Пока это не музыка.

Моя музыка:
http://www.last.fm/music/Orthonorma
http://www.myspace.com/186734155
http://soundcloud.com/orthonorma

Мой трек Our Morning Dream есть на сборнике Peace Therapy 3.
Под псевдонимом Emulsion есть альбом Under the Snow, в нете не нашёл, у меня есть точно.
Есть ещё пара треков под псевдонимами Dj Molotov и Clockwork Master.
Ещё дофига треков, которых в нете нет, но могу попробовать выложить.

воскресенье, 21 августа 2011 г.

Razor Extensions

Пример дополнения движка Razor собственными функциями.
Сначала, как для любого метода расширения, надо заиметь свой публичный статический класс и в нём определить публичные статические методы расширения того, что вы хотите, собственно, расширить.

В данном примере я расширил строковые и булевские переменные весьма простыми, но чрезвычайно полезными и короткими в употреблении, условиями:

public static class RazorExtensions
{   
       public static HelperResult IfHasValue(this string str
                                             Func<object, HelperResult> template)
       {
             return new HelperResult(writer =>
                                     {
                                        if (!string.IsNullOrWhiteSpace(str))
                                                template(str).WriteTo(writer);
                                     });
       }

       public static HelperResult IfTrue(this bool @bool
                                         Func<object, HelperResult> template)
       {
              return new HelperResult(writer =>
                                      {
                                         if (@bool)
                                                template(true).WriteTo(writer);
                                      });
       }
}

Примеры использования:

<a @Model.Boolean.IfTrue(@class="cur"href="@Url.Url()">Сслыка</a>

@Model.String.IfHasValue(@<p><big>@itembig>p>)

Стало ли лучше? )
Источники (раз, два)

SQL задачки

Решение пары бытовых задачек в sql server.
1. Надо было узнать, к каким колонкам и каким таблицам в базе привязан FILESTREAM:
select 
st.name as 'Table', 
sc.name as 'Column' 
from 
sys.columns sc
join 
sys.tables st on st.object_id = sc.object_id
where 
is_filestream = 1

2. Отследить прогресс бекапирования, целых два скрипта:
SELECT r.session_id,r.command,CONVERT(NUMERIC(6,2),r.percent_complete)
AS [Percent Complete],CONVERT(VARCHAR(20),DATEADD(ms,r.estimated_completion_time,GetDate()),20) AS [ETA Completion Time],
CONVERT(NUMERIC(10,2),r.total_elapsed_time/1000.0/60.0) AS [Elapsed Min],
CONVERT(NUMERIC(10,2),r.estimated_completion_time/1000.0/60.0) AS [ETA Min],
CONVERT(NUMERIC(10,2),r.estimated_completion_time/1000.0/60.0/60.0) AS [ETA Hours],
CONVERT(VARCHAR(1000),(SELECT SUBSTRING(text,r.statement_start_offset/2,
CASE WHEN r.statement_end_offset = -1 THEN 1000 ELSE (r.statement_end_offset-r.statement_start_offset)/2 END)
FROM sys.dm_exec_sql_text(sql_handle)))
FROM sys.dm_exec_requests r WHERE command IN ('RESTORE DATABASE','BACKUP DATABASE')


SELECT command,
            s.text,
            start_time,
            percent_complete,
            CAST(((DATEDIFF(s,start_time,GetDate()))/3600) as varchar) + ' hour(s), '
                  + CAST((DATEDIFF(s,start_time,GetDate())%3600)/60 as varchar) + 'min, '
                  + CAST((DATEDIFF(s,start_time,GetDate())%60) as varchar) + ' sec' as running_time,
            CAST((estimated_completion_time/3600000) as varchar) + ' hour(s), '
                  + CAST((estimated_completion_time %3600000)/60000 as varchar) + 'min, '
                  + CAST((estimated_completion_time %60000)/1000 as varchar) + ' sec' as est_time_to_go,
            dateadd(second,estimated_completion_time/1000, getdate()) as est_completion_time
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) s
WHERE r.command in ('RESTORE DATABASE', 'BACKUP DATABASE', 'RESTORE LOG', 'BACKUP LOG')


Может пригодится кому-нибудь, может быть даже снова мне )

суббота, 6 августа 2011 г.

BB-коды в qip

Думаю, многие, кто хотя бы иногда  обновляет qip, с некоторых пор стали замечать что картинки и видео можно просматривать прямо в окне сообщений, что есть достаточно приятное нововведение.
Недавно обнаружил также, что в чате можно применять BB-коды и украшать (или портить) текст: увеличивать размер, изменять цвет, вставлять код (!) с кривой подсветочкой и прочие радости жизни.
Полный список кодов с примерами тут.

пятница, 15 июля 2011 г.

Баг с css стилями

В целях SEO необходимо было по всему сайту заменить теги <hx> на теги <strong> и при этом сохранить соответствующие стили. Везде где в файлах стилей упоминался тег hx я подставлял свои классы, .shx. Теперь вот обнаружился интересный баг.
Было:
.offer h4.country a
Добавил свой:
.offer .sh4 .country a
Использование:
<h4 class="country">
На
<strong class="sh4 country">
Оказалось, что пробел между тегом и классом сыграл большую роль. Стили никак не подцеплялись. Поэтому будьте внимательны! Надо писать
.offer .sh4.country a
Без пробела!

среда, 6 июля 2011 г.

Сайт join.me

Вот такой простой, удобный и замечательный сайт подсмотрел у одного менеджера на работе.
Позволяет в пару кликов расшаривать свой рабочий стол и даже передавать управление им.
Опробовали с Никой. Результат прямо таки поражает. Общались через скайп, видео через join.me (там так же можно и гудеть и чатиться, но не пробовали). Скайповское видео рядом не валяется. Текст тут более чем читабелен, обновляется практически мгновенно, даже с моим убогим 2 мбит/сек и никто не достаёт сообщениями про "Как вам качество связи?", "Купите себе инторнет потолще!".
В общем, настоятельно рекомендую! Можно успешно помочь и быть помоченым.

понедельник, 20 июня 2011 г.

Text Templating failed to load...

Еще одна забавная ошибка терзает меня не первый месяц в VS2010. Не работает T4 (Text Template Transformation Toolkit), падает, в основном, с такой ошибкой (или предупреждением):

Package 'Microsoft.VisualStudio.TextTemplating.VSHost.OrchestratorPackage, Microsoft.VisualStudio.TextTemplating.VSHost.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' failed to load...

Эта хрень возникает после установки английской студии на машину, где раньше стояла русская. Разгадка таится в следующем ключе в реестре:

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\DSLTools\ShowWarningDialog

Злобная VS RU оставила нам там подарочек в виде значения:

Истина/Ложь

Так что есть смысл поменять на соответствующее нерусское слово (True/False) и радоваться.
Ссылка на баг репорт в Microsoft Connect

Проблемы с VS2010 SP1 | MS Security Essentials

Пол утра пытаюсь установить первый сервис пак на vs2010, при ужасно медлительной установке, и в результате стабильно получаю следующую ошибку:
"Microsoft Visual Studio 2010 Service Pack 1 cannot be installed because the state of this computer does not support it."
Кофиг такой: Windows 7, Visual Studio 2010 Professional, x86
Оказывается! Надо тупо доставить из оригинального установщика нечто под названием "Microsoft Office Developer Tools". Супер.
---
Помимо прочего TuneUp ругается на фиговые драйвера, имена которых начинаются на "MpKsl". Это нагадил туда MS Security Essentials. Снёс все с восклицательным знаком, не жалею.

вторник, 14 июня 2011 г.

Подменяем внешние библиотеки в зависимости от конфигурации

Один из проектов запущен на 64-х битном сервере, но на рабочих местах разработчиков в основном стоит x86 система. Я прикручивал систему логирования (elmah) в качестве внешней библиотеки и приходилось каждый раз при публикации заменять x86 файлы для тестирования разработки на версии x64.

Результатом стал небольшой скрипт, вписанный в события построения (Project Properties->Build Events):


if $(ConfigurationName) == Debug (
    xcopy /s/e/y/i/r/f "$(SolutionDir)Dlls\Elmah-x86" "$(TargetDir)"
) else ( 
    xcopy /s/e/y/i/r/f "$(SolutionDir)Dlls\Elmah-x64" "$(TargetDir)"
)

вторник, 7 июня 2011 г.

C# Nullable DateTime

Последнее время, когда я учился получать данные из бд, меня часто мучал вопрос, почему извлеченная нулевая дата (в базе == NULL) таковой не является? И почему я не могу написать DateTime dt = null? Надо было проявить чуть интереса.


[SerializableAttribute]
public struct DateTime : IComparable, IFormattable, 
 IConvertible, ISerializable, IComparable<DateTime>, 
 IEquatable<DateTime>

Да, DateTime это, оказывается, структура. А структура это value type и не может быть null, ответ на поверхности.
А для проверки некорректности даты следует использовать

dt == DateTime.MinValue
// DateTime.MinValue = 00:00:00.0000000 January 01, 0001

Также, конечно, можно использовать Nullable<DateTime> = "DateTime?".

Маленькая статейка по теме:
Nullable DateTime

четверг, 2 июня 2011 г.

Заметка от передаче файлов в ответе сайта

Замечали ли вы, что браузер ссылки на некоторые файлы пытается сразу открыть, а некоторые — сохранить? Например, pdf-файлы в браузере Chrome.
Вот ссылка, которая открывается в браузере.
Пример загружаемого файл, к сожалению, с налета привести сейчас не могу (если есть, приводите в комментах!), но разница заключается в одном ключе заголовка ответа (Response Header):
  1. Content-Disposition:
    attachment; filename="file.ext"

Описание ключа в статье на вики.
Так же там периодически мелькает информация о сервере и на чем реализована страница, что тоже явилось для меня небольшим, но открытием:
  1. Server:
    Microsoft-IIS/7.5
  2. X-AspNet-Version:
    2.0.50727
  3. X-Powered-By:
    ASP.NET


вторник, 31 мая 2011 г.

Проблемы с Web-страницами

Ни раз натыкался на одни и те же грабли, выраженные совершенно по разному.
Признаки:
  • Тотально разваливается верстка
  • Не работают базовые вещи (не отображается заголовок, кнопки)
  • И многое другое
Надо обратить внимание на то, чтобы все теги были закрыты, все строки и кавычки соответствовали. Иногда из-за одного символа ложиться весь сайт. Следите за тем, что пишете.
VS2010 должна проводить валидацию и соответствующие ошибки отображаются как warning.

воскресенье, 29 мая 2011 г.

Используем Fluent NHibernate с Oracle

Авторы позиционируют свой продукт как:
"Fluent, XML-less, compile safe, automated,convention-based mappings for NHibernate."

То есть в нашем проекте не будет xml. Совсем.
Скачать можно здесь: http://fluentnhibernate.org/

В этом посте расскажу как поднял.
Я использовал NuGet в VS2010. Понадобится пакет Fluent NHibernate (в моем случае версия 1.2.0.712). NuGet автоматически выкачает все зависимости.

Я предполагаю, что у вас уже есть:
  1. Некоторая база в Oracle Server.
  2. Установленные на клиентском компьютере Oracle ODAC или Oracle Client.
  3. Необходимые протестированные строки подключения.
Возьмем любую сущность, например фотоальбом, принадлежащий пользователю User и содержащий в себе фотографии Images (свойство Thumbnail не рассматривается):

Обратите внимание на то что мы используем private setter для Id, а так же для коллекций, которые инициализируются в конструкторе. Помимо этого все свойства помечены виртуальными, это необходимо для NHibernate.

Рассмотрим код для маппинга нашей сущности:
MappingNames представляет из себя мой статический класс со строковыми константами имен таблиц и колонок, используемых в БД, ибо эти значения используются в нескольких проектах.

Класс отображения надо унаследовать от обобщенного класса ClassMap<>.
Метод Id() отображает идентификаторы, которые, в нашем случае, генерируются выбранным sequence; Map() отображает соответствующие свойства (используя соглашение об именах свойств для отображения на поля БД, так же можно задавать вручную с помощью метода Column(string)); Reference() идентичено NHibernate'овскому many-to-one, HasMany() — one-to-many, в соответствующих сущностях эти свойства должны быть прописаны с точностью до наоборот.

Более подробно о методах маппинга вы можете прочитать в вики Fluent NHibernate.

Пример конфигурирования БД:
Далее, метод OpenSession() используется в репозиториях или в Dependency Injection

Не забывайте так же со всеми бинарниками таскать и соответствующие провайдеры драйверов, в моем случае (Oracle ODAC) — библиотека Oracle.DataAccess.dll. Надо выставлять в свойствах ее Reference: Copy Local = True. Пишите тесты, чтобы видеть что вообще работает.

Вот так компонент помогает избавиться от xml и сделать всю конфигурацию строго типизированной.

Вопросы?

Желаю гибкого коннекта.

пятница, 27 мая 2011 г.

Опыт использования R# 6

Выкачал парочку Early Access Program билдов шестого по счету решарпера.
Установленный не на SSD Гагаринский (12.04) билд, несмотря на свой рейтинг "Stable", сильно подтормаживал.
Заявлена поддержка JavaScript, CSS и, конечно же, Razor view engine.
Сейчас использую билд от 26.05. Периодически пишет в свой лог исключения, предлагает отправить — по возможности участвую, сразу на сайте в трекере видно. В целом VS2010 еще ни разу не упала. Мелкие глюки и недоработки R# практически никак не влияют на общее положительное впечатление от использования в новых областях.

суббота, 23 апреля 2011 г.

Групповая почта

В голову пришла идея сделать групповую почту, которая будет пересылать любые входящие письма на N адресов всех студентов группы.
Достоинства и примеры использования:
  • Если хотите предупредить всех, необходимо лишь отправить письмо на этот адрес.
  • Старостам не надо больше париться и решать, куда писать: на форум, в твиттер, на почту, в аську или куда нибудь еще.
  • От студентов больше не требуется никаких телодвижений, как то: регистрация на форуме, твиттере, регулярное посещение оных и прочее. Только лишь предоставить активный ящик и подтвердить согласие, большинство людей уже автоматизировало проверку личной почты.
  • Решает недостаток форума - невозможность подписаться на почту на новые сообщения.
  • Можно давать преподам для пересылки заданий, тогда они автоматически окажутся на почте каждого студента.
  • Администрирование сосредоточено в одном месте.
  • Каждый сам решает, какие сообщения ему сохранить, а какие нет, можно просто настроить фильтр и ярлыки.
  • Архив всегда есть на корневом ящике.
Недостатки:
  • Чтобы отписаться надо сообщить админу лично.
  • Возможно некоторое время безнаказанно флудить и спамить.

среда, 9 марта 2011 г.

foobar2000 experience

Закончил маленький, но весьма полезный на мой субъективный взгляд плагин для фубара (foo_trackexpand).
Суть его заключается в замене выбранных треков соответствующим альбомом или всеми треками данного исполнителя из медиа библиотеки. Иногда ищешь определенный трек, но хочешь послушать весь альбом включая искомое. Плагин решает эту задачу.
Для наглядности просто приведу парочку скриншотов:
Рис. 1. Пример простого использования

Рис. 2. Пример множественного использования

Любые отзывы, замечания и поправки приветствуются. Плагин далеко не идеален, поэтому если есть что то что, по Вашему мнению, он должен делать, но не делает или делает не так как ожидается — просто скажите об этом!


---

Так же в данный момент я, @maxxxover и @zolotarevDA ведем разработку плагина для полноценной интеграции foobar2000 с last.fm и vk.com (foo_lastfm).
Намеченный список (упорядочены в порядке убывания вероятности скорой реализации)
  • Скробблинг
  • Возможность добавлять трек в любимые не выходя из плеера.
  • Синхронизация количества прослушиваний
  • Встроенное дерево радиостанций di.fm
  • Переход на страницы исполнителей, треков, альбомов, пользователей
  • Просмотр и прослушивание любимых ♥ (favorite) композиций и кастомных плейлистов собственных, друзей или других пользователей на last.fm
  • Интегрированный поиск по last.fm и проигрывание произвольных треков, используя vk.com
  • Автоскачивание обложек
Запросы новых фич, уточнения, комментарии, пожертвования и помощь приветствуется =) Плагин потребует от Вас логин и пароль на соответствующих сайтах, использовать которые в корыстных целях нам нет никакого смысла. Можете хоть новые завести специально.
Спасибо за внимание.