Запись доклада с DevPRO: «Единый код C#: разрабатываем для Web, Desktop, Android, Windows RT и iOS»

Наконец-то стали появляться первые видеозаписи с прошедшего 16 марта семинара DevPRO.

На семинаре я выступал с докладом о разработке мобильных приложений с использованием c#.

Баг в help-page для WebAPI

Как известно, в ASP.Net MVC4 одной из главных появившихся фишек стал WebAPI.

Вместе с обновлением Web Tools 2012.2, вышедшем, как ни странно, в 2013, Майкрософт добавил к WebAPI интересную функцию — генерацию страницы помощи (help-page) с описанием вашего API в человеко-читаемом виде, и даже с примерами в виде xml и json. Большой плюс этой страницы в том, что информацию и описание API можно брать прямо из xml-комментариев к методам API-контроллера

Сегодня, однако, я натолкнулся на досадную ошибку в работе этой самой страницы помощи:
для метода вида

    /// <summary>
    /// description
    /// </summary>
    [HttpGet]
    public string Tst([FromUri] TstModel filter)
    {
        return null;
    }

Проблема, как оказалось, была в том, что TstModel я, как водится, объявил вложенным классом (nested class) в самом контроллере. Из-за этого help page слегка потерял голову и необходимой документации не увидел :)

Для интересующихся и/или столкнувшихся с той же самой проблемой, фикс прост:
XmlDocumentationProvider.GetTypeName

line 109: return type.FullName.Replace("+", "."); //was: return type.FullName
line 101: string typeName = genericType.FullName.Replace("+", "."); //was: string typeName = genericType.FullName

Может, кто подскажет, куда можно послать по этому поводу bug-report? :)
Кроме как через nuget письмом автору Microsoft.AspNet.WebApi.HelpPage — других вариантов не найдено :)

О стартапе-ловушке, или Роберт Мартин хочет нам навредить

Сделал перевод ответа Роба Эштона на заметку Роберта Мартина «О стартапе-ловушке».

После появления перевода оригинальной статьи дяди Боба не мог не ответить переводом зацепившего ответа :) Тема моя любимая — про тесты.

Не стесняйтесь плюсануть на хабре (http://habrahabr.ru/post/172039/), если понравится :)

Автогенерация комментариев в MonoDevelop

I love this feature!
И это реально то, чего не хватает в VS/Resharper :)

Попробуем добавить xml-комментарий к свойству:

    public UIViewController CurrentViewController {

Набираем традиционные «///» и получаем…

    /// <summary>
    /// Gets the current view controller.
    /// </summary>
    public UIViewController CurrentViewController {

Ну, я даже не знаю, что добавить :) Правда, иногда всё-таки приходится дописывать еще пару фраз :)

P.S. Может, кто-нибудь знает, как это сделать в VS?

RavenDB в «одноразовых» приложениях

На выходных попробовал RavenDB на небольшой задаче обработки массива документов. Документов было не очень много — порядка 50К, их обработка — задача разовая, но её длительность получалась однозначно порядка 10 часов, плюс всё это отлично параллелилось.
Поэтому возникла мысль загнать все эти документы в БД, чтобы без проблем сохранять промежуточные результаты и не волноваться за exception’ы, безвозвратно прерывающие обработку 10-часового процесса в самом конце :)
Raven-Embedded видился неплохим кандидатом для такого использования, поскольку позволял не париться с маппингами, быстро «установить» БД, просто добавив nuget пакет, позволял динамически добавлять в документы новые структуры данных (результаты обработок) ну и по идее должен был быстро работать :)
Что же из всего этого получилось?
Continue reading

Mac OS X и горячие клавиши

Работать в Mac OS X после стольких лет программирования в windows — это настоящий стресс :) Причина проста и банальна — очень многие сочетания клавиш, к которым мы привыкли работают по-другому, или вообще не работают :)
Собственно, основные проблемы идут от того, что Ctrl переехал на клавишу Win, а Home и End переходят в начало и конец файла (а не начало и конец строки, как в windows).

К счастью, Ctrl и Win меняются местами прямо в настройках МакОси (Системные настройки -> Клавиатура -> Клавиши модификации), а Home и End возвращаются к привычному PC-функционалу с помощью DoubleCommand или ему-подобных утилит.
Эти два небольших шага сэкономили мне множество нервов и позволили сосредоточиться на деле, а не перестройке собственных привычек :)

Прочие же привычные по VisualStudio сочетания можно перенастроить уже прямо в MonoDevelop.
И да простят меня апологеты Mac OS за такие издевательства над системой :)

P.S. Спасибо Брайану Ханкинсу за наводки

Публикация исходников вместе с nuget — плюс исходники Av.Infrastructure.Web

На выходных (где-то с месяц назад, когда я только взялся за этот пост) наконец-то дошли руки до публикации исходников своей «инфраструктурной» библиотеки. По правде говоря, я это собирался сделать достаточно давно, но насущной необходимости не было, да и сейчас наврядли кому-то понадобиться заточенная по большому счету под личные нужды одна из сотен тысяч других библиотек-собраний-всяких-мелочей, однако публикация исходников вместе со своими собственными nuget-пакетами таки может кому-нибудь пригодиться.
Continue reading

Презентация и исходники с вводного семинара по NHibernate

В рамках MccTomskCamp 18 июля проводил небольшой вводный семинар по NHibernate. Ссылки на видео, презентацию и исходные коды можно найти в конце поста, а можно и посмотреть прямо здесь:

P.S. Большое спасибо всем посетившим семинар за проявленное внимание к мероприятию :)/a

Ускорение билда asp.net MVC в 10 раз или RazorGenerator как альтернатива MvcBuildViews

Долгое время одним из первых шагов после создания нового MVC-сайта у меня было редактирование .csproj и добавление магического элемента

<mvcbuildviews>true</mvcbuildviews>

Напомню, что этой директивой включается компиляция Razor-вьюшек, таким образом об ошибках в .cshtml файлах можно узнать не в рантайме (при открытии веб-странички), а во время компиляции проекта. Опция, безусловно, очень удобная, но очень сильно замедляющая процесс сборки. Так, при отключенной опции наш средних размеров MVC-проект собирается за 1 секунду, а со включенной — за 10 секунд (в проекте всего лишь чуть больше 100 cshtml файлов).
Такая немаленькая задержка очень серьезно сказывается на разработке — по сути при каждом билде можно легко успеть «переключиться» на браузер и пролистать пару страничек :)

Таким образом от MvcBuildViews очень захотелось отказаться, но при этом не потерять возможность обнаружения ошибок во вьюшках во время компиляции.
Проблему решил замечательный RazorGenerator от Дэвида Эббо. РазорГенератор интегрируется в качестве Custom Tool для Visual Studio и преобразует каждую вьюшку в соответствующий c#-код, который и компилируется в момент компиляции проекта и выдает ошибки абсолютно аналогичные MvcBuildViews. При этом время компиляции с RazorGenerator’ом составляет(в нашем случае) ту же 1 секунду, что и без него (с отключенным MvcBuildView). Итоговый выигрыш — в 10 раз (10 сек — компиляция + MvcBuildViews, 1 сек — компиляция + RazorGenerator).
Continue reading

ModelUnbinder в T4MVC — работа со сложными моделями

В рамках ModelUnbinder, об основном сценарии использования которого я уже писал, была решена еще одна немаловажная проблема — работа со «сложными» моделями.
Рассмотрим пример: допустим, у нас на сайте есть форма поиска, и есть экшен, который показывает результаты:

        public class SearchModel
        {
            public string SearchString { get; set; }
            public bool InLocalArea { get; set; }
            public int Page { get; set; }
            public int PerPage { get; set; }
        }

        public virtual ActionResult Search(SearchModel searchModel)
        {
            return Json(searchModel, JsonRequestBehavior.AllowGet);
        }

Допустим, мы хотим дать ссылку на результаты какого-то поиска и хотим воспользоваться для этого T4MVC. Попробуем так:

<a href="@Url.Action(MVC.Home.Search(new HomeController.SearchModel()
             {
                 SearchString = "qweasd",
             }))">Предзабитый поиск1</a>

В результате у нас получится URL вроде: http://localhost:30729/Home/Search?searchModel=MvcApplication2.Controllers.HomeController.SearchModel. Это, конечно, не совсем то, что нужно :) Для решения проблемы воспользуемся ModelUnbinder’ом:

        protected void Application_Start()
        {
            //blablabla
            ModelUnbinderHelpers.ModelUnbinders.Add(typeof(HomeController.SearchModel), new PropertiesUnbinder());
        }

PropertiesUnbinder — это анбайндер, поставляемый в комплекте с T4MVC. Собственно, с его помощью в данном случае мы и получаем требуемый результат, ссылка теперь выглядит таким образом: http://localhost:30729/Home/Search?searchModel.SearchString=qweasd&searchModel.InLocalArea=False&searchModel.Page=0&searchModel.PerPage=0. Конечно, и этот URL можно чуть-чуть улучшить (например, не писать дефолтные значения value-type’ов), но по крайней мере эта ссылка вполне корректно работает, а в исходном коде нам пришлось поменять всего одну строчку — добавление анбайндера.

В реальной жизни в таких случаях я предпочитаю создавать пустой интерфейс IComplexModel, который реализуют все подобные модельки, и добавлять анбайндер уже только для этого интерфейса. Таким образом код выглядит как-то так:

        public interface IComplexModel { }
        public class SearchModel : IComplexModel
        {
            public string SearchString { get; set; }
            /* ... */
        }

        protected void Application_Start()
        {
            //blablabla
            ModelUnbinderHelpers.ModelUnbinders.Add(typeof(IComplexModel), new PropertiesUnbinder());
        }

Вот и всё! Можно лишь добавить, что PropertiesUnbinder отлично работает и с массивами внутри модели, то есть модель вида:

        public class SearchModel : IComplexModel
        {
            public int[] Numbers { get; set; }
        }

так же будет вполне адекватно преобразована в соответствующий URL.

Как обычно, тестовый проект с примером можно скачать и полюбопытствовать. Буду рад, если это кому-нибудь пригодиться.