<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-329418352356606474</id><updated>2024-09-01T06:51:41.856+03:00</updated><category term="JavaScript"/><category term="ASP.NET"/><category term="HTML"/><category term="LINQ"/><category term="jQuery"/><category term="Web Performance"/><category term="AJAX"/><category term="ASP.NET MVC"/><category term="Expression Trees"/><category term="Knockout"/><category term="UI"/><category term="IIS"/><category term="MVVM"/><category term="iOS"/><category term="ASP.NET MVC 3"/><category term="Bulk Operations"/><category term="Debug"/><category term="Networking"/><category term="SVN"/><category term="Tools"/><category term="Web Services"/><category term="bash"/><category term="command line"/><category term="mac"/><category term="Binding"/><category term="Caching"/><category term="Code Generation"/><category term="Custom Font"/><category term="Custom View"/><category term="Deferred"/><category term="HTTP"/><category term="MS SQL 2008"/><category term="Printing"/><category term="Promise"/><category term="Razor"/><category term="Render HTML"/><category term="Render View"/><category term="SQL"/><category term="SSRS"/><category term="Script Combining"/><category term="ScriptManager"/><category term="System Tools"/><category term="Usability"/><category term="View Engine"/><category term="Visual Studio"/><category term="WPF"/><category term="XHR"/><category term="XML"/><category term="XSD"/><category term="хобби"/><title type='text'>Vitaly Ivanov&#39;s blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default?start-index=26&amp;max-results=25'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>38</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-9001610737154011703</id><published>2015-01-30T17:11:00.002+02:00</published><updated>2015-01-30T17:15:07.374+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AJAX"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="Deferred"/><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="jQuery"/><category scheme="http://www.blogger.com/atom/ns#" term="Promise"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Services"/><title type='text'>Пример jQuery Deferred при работе с Ajax сервисами</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Если вам приходилось работать с web сервисами на javascript, возможно вы обращали внимание на то, что у них четкая структура ответа.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
Например:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;{
    &quot;status&quot;: &quot;401&quot;, 
    &quot;message&quot;: &quot;Authentication Required.&quot;
}

или 
{
    &quot;status&quot;: &quot;200&quot;,
    &quot;message&quot;: null,
    &quot;products&quot;: [
         { 
            &quot;id&quot;: 1, 
            &quot;title&quot;: &quot;t-shirt&quot;,
            ...
         },
         ...
    ]
}
&lt;/pre&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;&lt;/pre&gt;
&lt;div&gt;
Интересные статьи по дизайну API можно почитать &lt;a href=&quot;https://blog.apigee.com/front&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;, там же можно скачать брошюрку по дизайну REST сервисов.&lt;br /&gt;
&lt;br /&gt;
В этой статье мы будем говорить об использовании jQuery $.Defered на примере структуры запросов, которые использовал я у себя в проектах.&lt;br /&gt;
&lt;br /&gt;
Пример моей структуры:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;{
    &quot;success&quot;: true, /* Флаг об успешном выполнении операции. */ 
    &quot;error&quot;: null, /* Текст или объект ошибки, который можно показывать пользователю. */
    &quot;data&quot;: null /* Массив или объект. */
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;GET /employee/list

{
    &quot;success&quot;: true,
    &quot;error&quot;: null,
    &quot;data&quot;: [
         {
             &quot;id&quot;: 1,
             &quot;name&quot;: &quot;Eaton Cross&quot;,
             &quot;email&quot;: &quot;Duis.risus.odio@consectetuereuismod.org&quot;,
             &quot;phone&quot;: &quot;1-215-898-1399&quot;
         },
         {
             &quot;id&quot;: 2,
             &quot;name&quot;: &quot;Randall Johnson&quot;,
             &quot;email&quot;: &quot;vitae.diam.Proin@Sedcongue.ca&quot;,
             &quot;phone&quot;: &quot;1-918-519-4417&quot;
         },
         ...
    ]
}


POST /employee/create

{
    &quot;success&quot;: true,
    &quot;error&quot;: &quot;Email &#39;vitae.diam.Proin@Sedcongue.ca&#39; already in use. Please provide another email.&quot;,
    &quot;data&quot;: null
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример использования:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: true;&quot;&gt;$.getJSON(&#39;/employee/list&#39;)
    .success(function(response) {
        if (response.success == true) {            
            // 1. Парсим данные из response.data
            // 2. Показываем данные
        }
        else {
            // Показывает ошибку(и) из response.error
        }
    })
    .error(function(xhr, error, statusText){
         /* Показывает обший текст ошибки, т.к. сюда приходят ошибки сервера 
           (если запрос не обработался правильно) 
           и ошибка в следствии перезагрузки страницы до зовершения запроса. */
    })
    .always(function(){
         hideLoad() // Скрываем ajax крутилку
    });
&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Преимущество подобной структуры является однотипность, вы всегда знаете что у вас есть данные в одном поле, ошибка и сообщение в другом.&lt;br /&gt;
&lt;br /&gt;
В этом примере есть недостатки.&lt;br /&gt;
&lt;br /&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;В обработчике success у вас всегда код будет начинатся одинаково, с проверки на успешное выполнение. С одной стороны, вроде бы ничего, с другой, если код выполнился не по плану, значит он должен прийти в обработчик fail. Так же логичней? А в success только обработчик успешного выполнения кода на серевер.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Другая проблема в том, что сейчас в error будет вызыватся если пользователь перегружает страницу до завершения выполнения запроса или если запрос выполнился с ошибкой на сервере или страница не найдена и тп.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
Решим эти проблемы используя код с &lt;a href=&quot;http://delmadman.blogspot.com/2015/01/ajax.html&quot; target=&quot;_blank&quot;&gt;предыдущей статьи&lt;/a&gt;&amp;nbsp; немного усовершенствовав его.&lt;br /&gt;
Для начала напишем следующую функцию:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;function handleResponse (ajaxRequest) {
    var isUserAbortedRequest = function (xhr) {
        return !xhr.getAllResponseHeaders();
    }

    return $.Deferred(function (def) {
        ajaxRequest
            .error(function(xhr, error, statusText) {
                def.reject({ aborted: isUserAbortedRequest(xhr), error: error });
            })
            .success(function (response) {
                if (response.success == true) {
                    def.resolve(response.data);
                }
                else {
                    def.reject({ aborted: false, error: response.error });
                }
            });
        });
};

&lt;/pre&gt;
Эта функция нам пригодится, чтоб &quot;обвернуть&quot; ajax запрос и добавить изменения для обработки повторяющегося кода, возникающего в событии success, описанного выше.&lt;br /&gt;
&lt;br /&gt;
Каждый ajax запрос посылаемый с помощью jQuery возвращает объект jQuery&amp;nbsp;&lt;b&gt;promise&lt;/b&gt;&amp;nbsp;к которому можно цеплять обработчики done\success, error\fail, complete\always и таким образом следить за процессом выполения асинхронной операции. &lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;Promise&lt;/b&gt; - это шаблон проектирования, улучшающий органиазцию кода при работе с асинхронными операциями.&lt;br /&gt;
Шаблон используется также при работе с анимациями, например обработчики fadeIn, show и др подобные тоже возвращают &lt;b&gt;promise.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Очень удобная функция &lt;a href=&quot;http://api.jquery.com/jquery.when/&quot; target=&quot;_blank&quot;&gt;$.when&lt;/a&gt;&amp;nbsp;- она позволяет вам получать уведомления о процессе выполнения группы асинхронных операций. Допустим вам надо показать какое-то сообщение пользователю только тогда, когда все 3 ajax запроса выполнятся.&lt;br /&gt;
&lt;br /&gt;
Подбробней можно почитать на сайте &lt;a href=&quot;http://api.jquery.com/category/deferred-object/&quot; target=&quot;_blank&quot;&gt;jQuery&amp;nbsp;&lt;/a&gt;&amp;nbsp;и &lt;a href=&quot;https://www.google.com.ua/webhp?sourceid=chrome-instant&amp;amp;ion=1&amp;amp;espv=2&amp;amp;ie=UTF-8#q=jquery%20deferred%20habra&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;. Возможно я еще напишу о применени этого шаблона с примерами.&lt;br /&gt;
&lt;br /&gt;
Теперь по коду.&lt;br /&gt;
Функция handleResponse принимает ajax запрос и возвращает обвертку в виде $.Deferred. Для клиент-кода, который будет использовать эту функцию ничего не изменится.&lt;br /&gt;
&lt;br /&gt;
Наш перехватчик-обвертка смотрит, если запрос не выполнился на сервере, то в обработчике error мы проверяем почему он не выполнился, скорее всего из-за перезагрузки страницы или ошибки на сервере и говорим нашему promise объекту, чтоб он завершил наш ajax запрос, с ошибкой и аргументами aborted и error.&lt;br /&gt;
&lt;br /&gt;
Если мы получили ответ от сервера, смотрим успешно ли он выполнился, если нет, говорим нашему объекту promise завершить наш ajax запрос с ошибкой и передаем текст ошибки, который можно будет показать пользователю.&lt;br /&gt;
&lt;br /&gt;
Если все ОК, успешно завершаем наш promise объект с response.data.&lt;br /&gt;
&lt;br /&gt;
Сейчас код можно использовать так:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;handleResponse($.getJSON(&#39;/employee/list&#39;))
    .done(function(response) {
         // Уже работаем с данными через response.employees
    })
    .fail(function(e) {
        // Если это наша ошибка, показываем. В другому случае ничего не делаем
        if (!e.aborted) {
            alert(e.error);
        }
    })
    .always(function(){
         hideLoad() // Скрываем ajax крутилку
    });
&lt;/pre&gt;
&lt;br /&gt;
Success и error обработчики только для jQuery ajax запросов, это было сделано просто для логичных называний. Поскольку мы возвращаем обвертку через promise, то эти обрабочики недоступный, вместо них более общие done\fail.&lt;br /&gt;
&lt;br /&gt;
Цель выполнена, мы избавились от дублирующего кода и теперь результат ajax запроса приходит в обработчики как должно быть, по назначению и без лишних проверок.&lt;br /&gt;
&lt;br /&gt;
В таком виде код не очень удобно использовать, тем более есть еще POST запрос, который надо настраивать если вы общаетесь с сервером в JSON формате. Поэтому его надо отрефакторить.&lt;br /&gt;
&lt;br /&gt;
Вот, что получилось в итоге - легковесный класс для ajax запросов&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;var Ajax = (function ($) {

    var _postJson = function (url, data) {
        return $.ajax({
            type: &quot;POST&quot;,
            url: url,
            data: ko.toJSON(data),
            dataType: &#39;json&#39;,
            contentType: &#39;application/json&#39;
        });
    };

    var _getJson = function (url, data) {
        return $.getJSON(url, data);
    };

    var _handleResponse = function (ajaxRequest) {
        var isUserAbortedRequest = function (xhr) {
            return !xhr.getAllResponseHeaders();
        }

        return $.Deferred(function (def) {            
            ajaxRequest
                .fail(function(xhr, error, statusText) {
                    def.reject({ aborted: isUserAbortedRequest(xhr), error: error });
                })
                .success(function (response) {
                    if (response.success == true) {
                        def.resolve(response.data);
                    }
                    else {
                        def.reject({ aborted: false, error: response.error });
                    }
                });
        });
    };

    /* exports */
    return {
        post: function (relativeUrl, data) {
            return _handleResponse(_postJson(relativeUrl, data));
        },
        get: function (relativeUrl, data) {
            return _handleResponse(_getJson(relativeUrl, data));
        }
    };

})(jQuery);
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
Использовать так:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;Ajax.get(&#39;/employee/list&#39;)
    .done(function(response) { // Уже работаем с данными через response.employees })
    .fail(function(e) {        
        if (!e.aborted) {
            alert(e.error);
        }
    });

И для POST запросов

var parameters = {
    name: &#39;Jhon&#39;, 
    email: &#39;...&#39;
};

Ajax.post(&#39;/employee/create&#39;, parameters)
    .done(function(response) { 
        // Employee создался, возможно в response будет response.employee или id завист от вашего дизайна. 
    })
    .fail(function(e) {        
        if (!e.aborted) {
            /* Наш employee не создался, возможно валидация, показываем. 
               Возможно в e.error будет объект c валидационными ошибками. Это уже вам решать. */
            alert(e.error); 
        }
    });
&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
Пока все&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/9001610737154011703/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2015/01/jquery-deferred-ajax.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/9001610737154011703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/9001610737154011703'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2015/01/jquery-deferred-ajax.html' title='Пример jQuery Deferred при работе с Ajax сервисами'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-8554230710364719836</id><published>2015-01-23T17:28:00.001+02:00</published><updated>2015-01-23T17:28:32.164+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AJAX"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="jQuery"/><category scheme="http://www.blogger.com/atom/ns#" term="XHR"/><title type='text'>Ajax запрос и ошибка при перезагрузке страницы </title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Всем привет,&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Возможно вы сталкивались с ситуацией, когда вы делаете ajax запрос, он долго орабатывается на сервере и вы перегружаете страницу в надежде, что следующий раз он выполнится быстрей, но нет :) вы получаете ошибку.&lt;br /&gt;
Ниже пример такого запроса:&lt;/div&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;$.getJSON(&quot;/clients/list&quot;)
    .success(function(){ ... })
    .error(function(xhr, error, statusText){
 // ошибка выпадает здесь
    })
&lt;/pre&gt;
&lt;br /&gt;
Ошибка в указанном месте может возникать не только из-за того, что пользователь не дождался выполнения запроса до конца и перешел на другую страницу или перегрузил страницу во время выполенения, но и из-за ошибок на сервер, например 503 и тп.&lt;br /&gt;
&lt;br /&gt;
Но нас интересует именно случай, когда обработчик error срабатывает когда пользователь перегружает или уходит со страницы вовремя выполнения запроса, в этом случае браузер прерывает запрос.&lt;br /&gt;
&lt;br /&gt;
Как правило, в функции error разработчики показывают диалог с ошибкой на экран или информируют пользователя другими способами об ошибке.&lt;br /&gt;
&lt;br /&gt;
Когда у вас ajax запрос выполняется с ошибкой, у вас в обработчике нет никаких флагов и полей, которые говорят почему запрос не полнился. В документации к jquery &lt;a href=&quot;http://api.jquery.com/jQuery.ajax/&quot; target=&quot;_blank&quot;&gt;http://api.jquery.com/jQuery.ajax/&lt;/a&gt;&amp;nbsp;пишут, что в поле error (в моем примере) будет статус запроса. На практике такого не было. Напишите в коментариях, если у вас статусы работают.&lt;br /&gt;
&lt;br /&gt;
Теперь решение.&lt;br /&gt;
Если запрос выполнился, но с ошибкой (на сервере), вы получите полноценный HTTP ответ с хедерами и телом ответа, не важно каким. Но, если запрос был прерван - вы не получите HTTP ответ, следовательно вы не получите ни хедеры, ни тело ответа. Все :)&lt;br /&gt;
&lt;br /&gt;
Для проверки того, что запрос выполнился с ошибкой из-за перезагрузки страницы или ухода с нее, достаточно проверить хедеры ответа.&lt;br /&gt;
&lt;br /&gt;
Код с решением:&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;var isUserAbortedRequest = function (xhr) {
    return !xhr.getAllResponseHeaders();
}

$.getJSON(&quot;/clients/list&quot;)
    .success(function(){ ... })
    .error(function(xhr, error, statusText){
 if (!isUserAbortedRequest(xhr)) {
     // показаем ошибку
        } else {
     // ничего не показываем, перезагрузка или переход на другую страницу
        } 
    })
&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/8554230710364719836/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2015/01/ajax.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/8554230710364719836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/8554230710364719836'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2015/01/ajax.html' title='Ajax запрос и ошибка при перезагрузке страницы '/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-2234804776954519766</id><published>2014-07-29T16:12:00.000+03:00</published><updated>2014-07-30T19:47:35.213+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bash"/><category scheme="http://www.blogger.com/atom/ns#" term="command line"/><category scheme="http://www.blogger.com/atom/ns#" term="mac"/><category scheme="http://www.blogger.com/atom/ns#" term="SVN"/><title type='text'>Как получить сообщение последнего комита в SVN</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Если вам понадобиться сообщение последнего комита в SVN это можно сделать следующей командой&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
$ PROJECT_DIR=&quot;/Users/vitaly/Development/MyProject&quot;&lt;br /&gt;
$ svn up&lt;br /&gt;
$ svn log ${PROJECT_DIR} --xml --with-all-revprops -r committed | xmllint --xpath //msg/text\(\) --format -&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
Для этого у вас в контексте должна быть переменная &lt;b&gt;PROJECT_DIR &lt;/b&gt;в которой указан путь к проекту, например &lt;b&gt;PROJECT_DIR=&quot;/user/vitaly/development/MyProject&quot;&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Сначала делаем update, потом берем последний комит. Данные вернуться в виде xml, в котором будет тэг &lt;b&gt;msg&lt;/b&gt;&lt;msg&gt;. Использую встроенную утилиту&amp;nbsp;&lt;b&gt;xmllint&lt;/b&gt;&amp;nbsp;ищем через &lt;a href=&quot;http://en.wikipedia.org/wiki/XPath&quot; target=&quot;_blank&quot;&gt;xpath&lt;/a&gt; тэг &lt;b&gt;msg &lt;/b&gt;и берег текст внутри тэга.&lt;/msg&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;svn up - &lt;/b&gt;&lt;u&gt;обязательно&lt;/u&gt; перед svn log, а то можете получить пустой тэг &lt;log&gt;&lt;/log&gt; в ответе к svn log.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/2234804776954519766/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2014/07/svn_29.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/2234804776954519766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/2234804776954519766'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2014/07/svn_29.html' title='Как получить сообщение последнего комита в SVN'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-8047211632517150463</id><published>2014-07-22T20:23:00.000+03:00</published><updated>2014-07-22T20:23:08.067+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bash"/><category scheme="http://www.blogger.com/atom/ns#" term="command line"/><category scheme="http://www.blogger.com/atom/ns#" term="iOS"/><category scheme="http://www.blogger.com/atom/ns#" term="mac"/><category scheme="http://www.blogger.com/atom/ns#" term="SVN"/><title type='text'>Как добавить в svn файлы с &quot;@&quot; с командной строки</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
Если кто-то работал с svn из командной строки на mac, то возможно вы сталкивались с проблемой, что svn не понимает файлы с собакой &quot;@&quot;.&lt;br /&gt;
&lt;br /&gt;
Например, если вы хотите добавить файл menu-icon@2x.png выполнив команду svn add menu-icon@2x.png получите&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
svn add menu-icon@2x.png&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
svn: warning: W155010: &#39;........FILE PATH..../menu-icon&#39; not found&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
svn: E200009: Could not add all targets because some targets don&#39;t exist&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
svn: E200009: Illegal target for the requested operation&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
Это решается добавлением &quot;@&quot; к название файла&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
vitaly$ svn add menu-icon@2x.png@&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; menu-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
Narnia:Slice vitaly$&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Допустим у вас есть целая папка с такими файлами&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
vitaly$ svn status&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; Splash-568h@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; Splash@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; background-568h@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; background@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; login-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; loupe-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; menu-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; password-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
? &amp;nbsp; &amp;nbsp; &amp;nbsp; reports-icon@2x.png&lt;/div&gt;
&lt;span style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;? &lt;/span&gt;&lt;span style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;settings-icon@2x.png &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
По одному добавлять не удобно... Используем то, что уже знаем + pipe&#39;ы и пишем следующий набор команд&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
vitaly$ ls | awk &#39;{print $1&quot;@&quot; }&#39; | xargs svn add&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; Splash-568h@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; Splash@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; background-568h@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; background@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; login-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; loupe-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; menu-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; password-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; reports-icon@2x.png&lt;/div&gt;
&lt;div style=&quot;background-color: black; color: #fffda9; font-family: Menlo; font-size: 12px;&quot;&gt;
A&amp;nbsp; (bin)&amp;nbsp; settings-icon@2x.png&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;ls&lt;/b&gt; - показывает список файлов в текущей папке&lt;br /&gt;
&lt;b&gt;awk&lt;/b&gt; - сканер по патерну, аля regex. То, что в кавычках это команда которую мы выполняем если паттерн подошел. $1 будет название файла. &quot;@&quot; - то, что мы добавляем к названию файла&lt;br /&gt;
&lt;b&gt;xargs&lt;/b&gt; - выполняем команду.&lt;br /&gt;
&lt;br /&gt;
Таким же образом можно использовать и &lt;b&gt;svn revert&lt;/b&gt;&amp;nbsp;и тп.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/8047211632517150463/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2014/07/svn.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/8047211632517150463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/8047211632517150463'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2014/07/svn.html' title='Как добавить в svn файлы с &quot;@&quot; с командной строки'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-6927649146372750032</id><published>2013-07-01T18:59:00.001+03:00</published><updated>2013-07-01T18:59:54.001+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Printing"/><title type='text'>Как разбить контент по страницам перед window.print</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Допустим у вас есть страница, которая поддерживает печать с браузера через &lt;b&gt;window.print() &lt;/b&gt;и на этой странице 1 график и одна таблица.&lt;br /&gt;
Для того чтоб график был на 1 странице а таблица на 2 нужно вставить между элементами элемент-разделитель со стилей &lt;b&gt;style=&quot;page-break-after: always&quot; :&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;

&lt;br /&gt;
&lt;pre class=&quot;brush: html;&quot;&gt;content here
&quot;
&lt;div style=&quot;page-break-after: always;&quot;&gt;
&lt;/div&gt;
&quot;
&quot;
content here&lt;/pre&gt;
&lt;br /&gt;
Полная статья &lt;a href=&quot;http://www.javascriptkit.com/dhtmltutors/pagebreak.shtml&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/6927649146372750032/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2013/07/windowprint.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/6927649146372750032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/6927649146372750032'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2013/07/windowprint.html' title='Как разбить контент по страницам перед window.print'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-326061927897278207</id><published>2013-05-31T14:37:00.000+03:00</published><updated>2013-05-31T14:37:51.245+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="Razor"/><category scheme="http://www.blogger.com/atom/ns#" term="Render HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="Render View"/><category scheme="http://www.blogger.com/atom/ns#" term="View Engine"/><title type='text'>Как отрендерить ASP.NET MVC страницу в строку</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Возможно, у вас была необходимость просто получить готовый HTML вашей страницы для отправки на почту или хранить как отчет и тд.&lt;br /&gt;
&lt;br /&gt;
Как ?&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;public class ViewRenderer
    {
        public static string RenderView(string viewName, ControllerContext controllerContext, object model)
        {
            ViewEngineResult view = ViewEngines.Engines.FindView(controllerContext, viewName, null);
            controllerContext.Controller.ViewData.Model = model;

            using (var writer = new StringWriter())
            {
                ViewContext context = new ViewContext(
                    controllerContext,
                    view.View,
                    controllerContext.Controller.ViewData,
                    controllerContext.Controller.TempData,
                    writer);

                view.View.Render(context, writer);
                writer.Flush();

                return writer.ToString();
            }
        }
    }
&lt;/pre&gt;
&lt;br /&gt;
Как пользоваться ?&lt;br /&gt;
Передаем название view, которое хотим отрендерить, ControllerContext у вас есть, это свойство в вашем контролере. Последний параметр - ваш класс модель с данными если нужно.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp;&quot;&gt;string html = ViewRenderer.RenderView(&quot;YTDClientReport&quot;, ControllerContext, YourViewModelInstance);
&lt;/pre&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/326061927897278207/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2013/05/aspnet-mvc_31.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/326061927897278207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/326061927897278207'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2013/05/aspnet-mvc_31.html' title='Как отрендерить ASP.NET MVC страницу в строку'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-7868952545499730222</id><published>2013-05-21T22:44:00.001+03:00</published><updated>2013-05-21T22:44:31.057+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Custom Font"/><category scheme="http://www.blogger.com/atom/ns#" term="iOS"/><title type='text'>Как применить свой ttf шрифт в iOS приложении</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Возможно вам приходилось или прийдется использовать нестандартные шрифты, которых нет в iOS.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Показываю как:&lt;/div&gt;
&lt;div&gt;
1. Добавляем шрифт в папку Supporting Files. В моем случае это AG_Friguer.ttf&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicuT3MLqHPnbjvMR_sVT3ZQS1oTFK4StPOiE59UMcezEEd_wfGsyLyt_6vybJ3aAa9DmEBuMGgMIvk2mzk-L7KW-OtvQP94GUqhWGSejlxvwbDfGVZQ35_mZchEwfRLK7l-kgXeyYLfsM/s1600/Screen+Shot+2013-05-21+at+10.19.31+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;229&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicuT3MLqHPnbjvMR_sVT3ZQS1oTFK4StPOiE59UMcezEEd_wfGsyLyt_6vybJ3aAa9DmEBuMGgMIvk2mzk-L7KW-OtvQP94GUqhWGSejlxvwbDfGVZQ35_mZchEwfRLK7l-kgXeyYLfsM/s320/Screen+Shot+2013-05-21+at+10.19.31+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
2. Открываем plist файл и добавляем следующий ключ &quot;Fonts provided by application&quot;. Добавляем элемент в этот ключ - &lt;b&gt;название файла с расгирением&lt;/b&gt; шрифта, это важно, не имя шрифта, а так как называется файл, который вы добавили в Supporting Files.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYEk68DV-7NdnUcdvmh6-2gh1rmqGl1SPwgBQ-vcI4_cHka-Ie5fanGCHVdF9vzaBBSea-sOXvOd99T1BsO9z5UOMku_Wimd_2G2aCR4cuHgMgixwP-huGyKXtIDCSUIQlm_qhPxcYVeM/s1600/Screen+Shot+2013-05-21+at+10.23.22+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;117&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYEk68DV-7NdnUcdvmh6-2gh1rmqGl1SPwgBQ-vcI4_cHka-Ie5fanGCHVdF9vzaBBSea-sOXvOd99T1BsO9z5UOMku_Wimd_2G2aCR4cuHgMgixwP-huGyKXtIDCSUIQlm_qhPxcYVeM/s320/Screen+Shot+2013-05-21+at+10.23.22+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
3. Для того, чтобы использовать шрифт вам нужно знать его имя. Имя можно узнать через утилиту Font Book на маке. Запускаем ее, добавляем шрифт, выбираем Install Checked.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo3Yl2kWeceviDx0juSQcR_o4FGav4pqXmEfHkOzkEAO8u657Hf4QfCuQIbyi_Mrjk25FZWY4PbZ9iZq43qy1WTYbm9ISvkK37-c-L7v5SGY2GM9TY3bJIPIY1U4OAeBSGSiHKr0FitmQ/s1600/Screen_Shot_2013-05-21_at_10.31.00_PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;278&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo3Yl2kWeceviDx0juSQcR_o4FGav4pqXmEfHkOzkEAO8u657Hf4QfCuQIbyi_Mrjk25FZWY4PbZ9iZq43qy1WTYbm9ISvkK37-c-L7v5SGY2GM9TY3bJIPIY1U4OAeBSGSiHKr0FitmQ/s320/Screen_Shot_2013-05-21_at_10.31.00_PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Далее смотрим имя шрифта. Как видим настоящее название &lt;b&gt;AGFriquer&lt;/b&gt;. Именно это название мы будем использовать в себя в коде.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi45to3H3i2LoBt04xSksZ8hS4zCkahNlvp3f1V_8nmTh7zQUbMesviE8fa3RiTLTSPijfIuy-GzcP80qfQBw1sYqiMCQQZZw8P0WGdaxRVLlVyh1u_72-Mj6yirPa8EQXndExELk488cs/s1600/Screen+Shot+2013-05-21+at+10.35.11+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;186&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi45to3H3i2LoBt04xSksZ8hS4zCkahNlvp3f1V_8nmTh7zQUbMesviE8fa3RiTLTSPijfIuy-GzcP80qfQBw1sYqiMCQQZZw8P0WGdaxRVLlVyh1u_72-Mj6yirPa8EQXndExELk488cs/s320/Screen+Shot+2013-05-21+at+10.35.11+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
4. Использовать не сложно&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #3495af; font-family: Menlo; font-size: 11px;&quot;&gt;
&lt;span style=&quot;color: black;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;_topicTitleLabel&lt;span style=&quot;color: black;&quot;&gt;.&lt;/span&gt;font&lt;span style=&quot;color: black;&quot;&gt; = [&lt;/span&gt;UIFont&lt;span style=&quot;color: black;&quot;&gt; &lt;/span&gt;fontWithName&lt;span style=&quot;color: black;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #b4261a;&quot;&gt;@&quot;AGFriquer&quot;&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt; &lt;/span&gt;size&lt;span style=&quot;color: black;&quot;&gt;:18.0f];&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;color: #3495af; font-family: Menlo; font-size: 11px;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
5. Результат&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVczKnZL0zU8u7U37YvgsqwPG4yAcmIAqLuJelZVMnUtoenSMKr6lBHNbOmHNLq_Xx-tkZ8FbOuRDjQfEDvzvHJTvg1MCiZ7xfJiWWptyE6LJa-54n-zDmreevKB8FSqdpzHA-zDBEHEY/s1600/Screen+Shot+2013-05-21+at+10.40.09+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;140&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVczKnZL0zU8u7U37YvgsqwPG4yAcmIAqLuJelZVMnUtoenSMKr6lBHNbOmHNLq_Xx-tkZ8FbOuRDjQfEDvzvHJTvg1MCiZ7xfJiWWptyE6LJa-54n-zDmreevKB8FSqdpzHA-zDBEHEY/s200/Screen+Shot+2013-05-21+at+10.40.09+PM.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/7868952545499730222/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2013/05/ttf-ios.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/7868952545499730222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/7868952545499730222'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2013/05/ttf-ios.html' title='Как применить свой ttf шрифт в iOS приложении'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicuT3MLqHPnbjvMR_sVT3ZQS1oTFK4StPOiE59UMcezEEd_wfGsyLyt_6vybJ3aAa9DmEBuMGgMIvk2mzk-L7KW-OtvQP94GUqhWGSejlxvwbDfGVZQ35_mZchEwfRLK7l-kgXeyYLfsM/s72-c/Screen+Shot+2013-05-21+at+10.19.31+PM.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-4891349780741171607</id><published>2013-05-12T14:22:00.001+03:00</published><updated>2013-05-12T14:22:10.267+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Custom View"/><category scheme="http://www.blogger.com/atom/ns#" term="iOS"/><title type='text'>Как создать UIView из Nib файла</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Если вы хотите сделать красивое приложение под iOS, то вам не обойтись без кастомных компонентов, которые наследуются от UIView или других элементов. Сами элементы отображения можно создавать самостоятельно в init&#39;ах, а можно и заранее разметить их в Nib файле.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
В первом случае не возникает трудностей, достаточно просто создать экземпляр вашего класса.&lt;/div&gt;
&lt;div&gt;
Для второго слачая с Nib файлом подготовил категорию. Я предоставляю 2 варианта, оба работаю, пользуйтесь тем, который больше нравится&lt;/div&gt;

&lt;pre class=&quot;brush: cpp; gutter: true;&quot;&gt;
//UIView+UIInitialization.h

#import &lt;UIKit/UIKit.h&gt;

@interface UIView (UIInitialization)

+ (UIView *) viewWithNibName:(NSString *)nibName owner:(NSObject *)owner;

@end



// UIView+UIInitialization.m Version 1

@implementation UIView (UIInitialization)

+ (UIView *) viewWithNibName:(NSString *)nibName owner:(NSObject *)owner
{   
    NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:owner options:NULL];
    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    id customView = nil;
    NSObject* nibItem = nil;
    while ((nibItem = [nibEnumerator nextObject]) != nil) {
        if ([nibItem isKindOfClass:[self class]]) {
            customView = nibItem;
            break;
        }
    }
    return customView;
}

@end


// UIView+UIInitialization.m Version 2

@implementation UIView (UIInitialization)

+ (UIView *) viewWithNibName:(NSString *)nibName owner:(NSObject *)owner
{
    UINib *nib = [UINib nibWithNibName:nibName bundle:nil];
    NSArray *nibArray = [nib instantiateWithOwner:owner options:nil];
    id customView = [nibArray objectAtIndex: 0];  
    
    return customView;
}

@end

&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/4891349780741171607/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2013/05/uiview-nib.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4891349780741171607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4891349780741171607'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2013/05/uiview-nib.html' title='Как создать UIView из Nib файла'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-2828921901093735222</id><published>2013-05-08T14:23:00.000+03:00</published><updated>2015-02-06T17:16:33.572+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Debug"/><category scheme="http://www.blogger.com/atom/ns#" term="HTTP"/><category scheme="http://www.blogger.com/atom/ns#" term="Networking"/><category scheme="http://www.blogger.com/atom/ns#" term="Tools"/><title type='text'>Инструменты разработчика. Отправляем HTTP запросы</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Для тестирования HTTP запросов я всегда пользовался утилитой&amp;nbsp;&lt;a href=&quot;http://fiddler2.com/&quot; target=&quot;_blank&quot;&gt;Fiddler&lt;/a&gt;. В ней есть вкладка Composer. Если кто не знает, пора почитать.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj65itSuhcSp7ZYht0Li51AIompspqCupR5bcsEUW24j17vDp5x2Fd4kikWqwPtYYjkOFrXKE7D1e3OgLaelsS0uIwtRi9hMnfiqOrnNQptZTFyf75pC4KAz3kz4xaTpaMQ77jE8pGb8Bk/s1600/2013-05-08_1413.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj65itSuhcSp7ZYht0Li51AIompspqCupR5bcsEUW24j17vDp5x2Fd4kikWqwPtYYjkOFrXKE7D1e3OgLaelsS0uIwtRi9hMnfiqOrnNQptZTFyf75pC4KAz3kz4xaTpaMQ77jE8pGb8Bk/s640/2013-05-08_1413.png&quot; height=&quot;208&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Все вроде бы хорошо, но не всегда удобно, например окно TextWizard, форматирование и тп.&lt;/div&gt;
&lt;div&gt;
Сегодня разговор не о фидлере, а об альтернативной утлите &lt;a href=&quot;https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm&quot; target=&quot;_blank&quot;&gt;Postman&lt;/a&gt;. Она идет как плагин к Chrome.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
Чем хорош&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Удобный в использовании&lt;/li&gt;
&lt;li&gt;Есть история запросов&lt;/li&gt;
&lt;li&gt;Форматирует ответы JSON/XML&lt;/li&gt;
&lt;li&gt;Есть горячие клавишы&lt;/li&gt;
&lt;li&gt;Не нужно ставить&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Пример&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit1v95pk86W48tDjJ1a2_a7eIxIT1ulEm3rq5sWVi1r5EVBonS0wRTVodrfP6C2lcVvFuqOQhDMa2Chau0CyG4EMgfG5_bI7F1SbeTPO1-hAosXt0VDB0FcJgLsGwR7H8AZrfSGMmIYAQ/s1600/2013-05-08_1410.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit1v95pk86W48tDjJ1a2_a7eIxIT1ulEm3rq5sWVi1r5EVBonS0wRTVodrfP6C2lcVvFuqOQhDMa2Chau0CyG4EMgfG5_bI7F1SbeTPO1-hAosXt0VDB0FcJgLsGwR7H8AZrfSGMmIYAQ/s640/2013-05-08_1410.png&quot; height=&quot;312&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Пользуйтесь!&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/2828921901093735222/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2013/05/http.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/2828921901093735222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/2828921901093735222'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2013/05/http.html' title='Инструменты разработчика. Отправляем HTTP запросы'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj65itSuhcSp7ZYht0Li51AIompspqCupR5bcsEUW24j17vDp5x2Fd4kikWqwPtYYjkOFrXKE7D1e3OgLaelsS0uIwtRi9hMnfiqOrnNQptZTFyf75pC4KAz3kz4xaTpaMQ77jE8pGb8Bk/s72-c/2013-05-08_1413.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-4826040256022559633</id><published>2013-05-07T16:06:00.000+03:00</published><updated>2013-05-08T14:31:40.821+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="IIS"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Performance"/><title type='text'>Как ускорить запуск ASP.NET MVC приложения</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Бывают случаи, когда вам говорят &quot;у меня долго открывается сайт&quot; или тп. Вы заходите на сайт чтоб это проверить и все загружается быстро и вроде как проблемы нет.&lt;br /&gt;
Проблема обычно возникает у тех, кто заходит на сайт после того как он не использоваться некоторое долгое время.&lt;br /&gt;
Так работает IIS. Когда приложение не используется долгое время оно выгружается и память отдается активным приложениям. Ваш сайт перегружается когда вы вновь заходите на любую страницу.&lt;br /&gt;
&lt;br /&gt;
Как решить:&lt;br /&gt;
1. Находим ваш сайт в IIS и выбираем Advanced Settings. Запоминаем Application Pool.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLPXzmVzYEf0Tv9oj957-uEKITPrM5-pVEdwPiaFPyADf2VoL2Jp0jbSHIGZrtfMIIX1sR8jAqdC840nWv0nplXvnfEdUwHHpx6xfl3QMNIWdXNPtdwsGXt4jmbSstM8_tn5kzePdMFdo/s1600/1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;233&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLPXzmVzYEf0Tv9oj957-uEKITPrM5-pVEdwPiaFPyADf2VoL2Jp0jbSHIGZrtfMIIX1sR8jAqdC840nWv0nplXvnfEdUwHHpx6xfl3QMNIWdXNPtdwsGXt4jmbSstM8_tn5kzePdMFdo/s640/1.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
2. Идем в Application Pools. Выбираем наш и Advanced Settings для пула.&lt;br /&gt;
3. Ставим параметр Idle Time-out = 0. Теперь наш сайт не будет выгружаться из памяти.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0JgCIptDxrkxjhgRrpamn8v3Ncnfi5Us4_gMC8-823rM5mZJUnmTLhFliP8MmrIEMA_PrHF1XE82ikKzW6Nhu0r3WF9iRClRbpRuZZeiY209_UNkfofRPjIfk8rPJQC8EqFkD1ZUE_1U/s1600/2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;362&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0JgCIptDxrkxjhgRrpamn8v3Ncnfi5Us4_gMC8-823rM5mZJUnmTLhFliP8MmrIEMA_PrHF1XE82ikKzW6Nhu0r3WF9iRClRbpRuZZeiY209_UNkfofRPjIfk8rPJQC8EqFkD1ZUE_1U/s640/2.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
4. Выбираем свой сервер затем Configuration Editor&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3C9FSsbzzRwYbhorSTe8Oh_dVoo9oTssN5jl1DBuW3w2kZ9YyHhetF6UflUT9Y4F7Xzv8DhsYzRo_XrvSu9Q2XF-zdsRp_sx0CXKGwRTMXhPojlfwpIWDIFdLT3xOPGFF9627TDDb504/s1600/3.1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3C9FSsbzzRwYbhorSTe8Oh_dVoo9oTssN5jl1DBuW3w2kZ9YyHhetF6UflUT9Y4F7Xzv8DhsYzRo_XrvSu9Q2XF-zdsRp_sx0CXKGwRTMXhPojlfwpIWDIFdLT3xOPGFF9627TDDb504/s1600/3.1.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
5. В Configuration Editor в выпадающем списке ищем applicationPools.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidudBKMReZ2nDVciXAs_mO2YveUL4sYBD-LTBlpZFVflRANaqe9dITiXZuqPhZrcABMGlkOAg9aY_AvD9rd-X44sVKOOHMi0IspQDK95-M09DU2kI8rJFPW76QjxoYmyTrkL8fFfnHlbM/s1600/3.2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidudBKMReZ2nDVciXAs_mO2YveUL4sYBD-LTBlpZFVflRANaqe9dITiXZuqPhZrcABMGlkOAg9aY_AvD9rd-X44sVKOOHMi0IspQDK95-M09DU2kI8rJFPW76QjxoYmyTrkL8fFfnHlbM/s1600/3.2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
6. Проверяем чтоб autoStart = True, startMode = AlwaysRunning. Это значит, что сайт будет стартовать когда запуститься IIS.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwbbx0vJA9lp54j_oNMdvkqb-FijQ7XabBTUGVRGSFYK4vdL1M1xMNR2Tmn2QKm47tTcwhPAbbjvMEwhApu2qqzOPWOXmbaVY9d_4vUBVNZb9YjORpwKRoKC13fCuKnaexkjJcMCJFz2A/s1600/4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;394&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwbbx0vJA9lp54j_oNMdvkqb-FijQ7XabBTUGVRGSFYK4vdL1M1xMNR2Tmn2QKm47tTcwhPAbbjvMEwhApu2qqzOPWOXmbaVY9d_4vUBVNZb9YjORpwKRoKC13fCuKnaexkjJcMCJFz2A/s640/4.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Все&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/4826040256022559633/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2013/05/aspnet-mvc.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4826040256022559633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4826040256022559633'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2013/05/aspnet-mvc.html' title='Как ускорить запуск ASP.NET MVC приложения'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLPXzmVzYEf0Tv9oj957-uEKITPrM5-pVEdwPiaFPyADf2VoL2Jp0jbSHIGZrtfMIIX1sR8jAqdC840nWv0nplXvnfEdUwHHpx6xfl3QMNIWdXNPtdwsGXt4jmbSstM8_tn5kzePdMFdo/s72-c/1.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-8645266931664989026</id><published>2012-11-02T14:33:00.000+02:00</published><updated>2012-11-02T14:33:09.386+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Networking"/><category scheme="http://www.blogger.com/atom/ns#" term="System Tools"/><title type='text'>Как завершить процесс блокирующий порт</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Недавно мне пришлось устанавливать &lt;a href=&quot;http://www.caucho.com/&quot;&gt;Resin &lt;/a&gt;веб сервер на windows для сайта написанного на Java. Когда я запускал сервер с консоли я получал сообщения об ошибке, что порты, которые я настроил для сайтов заняты другими процессами. Почему заняты - не понятно.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы узнать, какие процессы используют порты можно воспользоваться командой NETSTAT с ключами -a -o:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBC9Vcd8_FdOXvic388G9HFD76UrJUGppeKX6LROosEuJNyUEQ_nyQBDRzkrrMviQtp6iKTHLVnpBM66D3F8k_OhBbdPWfIpjMeS5R6Lhi7lTMoHM5gwYyasvLXf4tbZeArvK1J7e2tys/s1600/2012-11-02_1421.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBC9Vcd8_FdOXvic388G9HFD76UrJUGppeKX6LROosEuJNyUEQ_nyQBDRzkrrMviQtp6iKTHLVnpBM66D3F8k_OhBbdPWfIpjMeS5R6Lhi7lTMoHM5gwYyasvLXf4tbZeArvK1J7e2tys/s1600/2012-11-02_1421.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Допустим вам нужен порт 2559 на 127.0.0.1. В данном примере он занят процессом 3788.&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы завершить процесс можно воспользоваться командой &lt;b&gt;TASKKILL &lt;/b&gt;c ключами &lt;b&gt;/PID &lt;/b&gt;для указания процесса и можно&lt;b&gt; /F &lt;/b&gt;чтоб завергить его принудительно&lt;b&gt;.&lt;/b&gt;&lt;br /&gt;
Например &lt;b&gt;taskkill /f /pid 3788&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;
Дополнение.&lt;br /&gt;
Если вы не хотите видеть весь список процессов netstat, вы можете перенаправить результат в канал и обработать командой &lt;b&gt;FIND.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Например я хочу найти все процессы которые блокируют порты, начинающиеся с 49&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6YyMThzTemDSXxpk55c5yJhC0R5USb6WB0klt1b79T2FD_NHCluhiouOc9dghpF8V2cWn2myLPOt9QHbx4ZLRbDCne0SlVt5zLqNOZghPOcQ3ybOB5b8Xzn-1xgq2xNqJfw7jB5tRmxo/s1600/2012-11-02_1430.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6YyMThzTemDSXxpk55c5yJhC0R5USb6WB0klt1b79T2FD_NHCluhiouOc9dghpF8V2cWn2myLPOt9QHbx4ZLRbDCne0SlVt5zLqNOZghPOcQ3ybOB5b8Xzn-1xgq2xNqJfw7jB5tRmxo/s1600/2012-11-02_1430.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/8645266931664989026/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2012/11/blog-post.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/8645266931664989026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/8645266931664989026'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2012/11/blog-post.html' title='Как завершить процесс блокирующий порт'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBC9Vcd8_FdOXvic388G9HFD76UrJUGppeKX6LROosEuJNyUEQ_nyQBDRzkrrMviQtp6iKTHLVnpBM66D3F8k_OhBbdPWfIpjMeS5R6Lhi7lTMoHM5gwYyasvLXf4tbZeArvK1J7e2tys/s72-c/2012-11-02_1421.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-1557007687387900397</id><published>2012-07-08T16:27:00.000+03:00</published><updated>2012-07-08T16:27:11.501+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="jQuery"/><category scheme="http://www.blogger.com/atom/ns#" term="Knockout"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="UI"/><title type='text'>Ограничиваем ввод только цифрами с помощью кастомного биндинга Knockout</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Я уже писал как можно применить кастомный биндинг, чтоб &lt;a href=&quot;http://delmadman.blogspot.com/2012/01/jquery-datepicker-c-knockoutjs.html&quot;&gt;прицепить jquery datepicker&lt;/a&gt;. Сегодня я покажу еще один пример.&lt;br /&gt;
Иногда возникает необходимость ограничить пользовательский ввод по какому-то критерию, например разрешить вводить только цифры или только текст без цифр, если это имя или город.&lt;br /&gt;
В данной статье я покажу как ограничить ввод только цифрами, но в дальнейшем можно будет развить эту тему и фильтровать на основе какого-нибудь дополнительного критерия.&lt;br /&gt;
Решение по фильтрации я не изобретал и взял &lt;a href=&quot;http://stackoverflow.com/a/995193/344895&quot;&gt;первое попавшееся на stackoverflow&lt;/a&gt;. Его мы и будем использовать.&lt;br /&gt;
&lt;br /&gt;
Начнем с написания кастомного биндинга.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt; ko.bindingHandlers.inputFilter = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var filter = ko.utils.unwrapObservable(valueAccessor());

            if (filter == &#39;Numbers&#39;) {
                $(element).keydown(function (event) {
                    // Allow: backspace, delete, tab, escape, and enter
                    if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
                    // Allow: Ctrl+A
            (event.keyCode == 65 &amp;amp;&amp;amp; event.ctrlKey === true) ||
                    // Allow: home, end, left, right
            (event.keyCode &amp;gt;= 35 &amp;amp;&amp;amp; event.keyCode &amp;lt;= 39)) {
                        // let it happen, don&#39;t do anything
                        return;
                    }
                    else {
                        // Ensure that it is a number and stop the keypress
                        if (event.shiftKey || (event.keyCode &amp;lt; 48 || event.keyCode &amp;gt; 57) &amp;amp;&amp;amp; (event.keyCode &amp;lt; 96 || event.keyCode &amp;gt; 105)) {
                            event.preventDefault();
                        }
                    }
                });
            }

        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            // we don&#39;t need update.
        }
    };

function CarViewModel (){
   this.Age = ko.observable(10);
};

var car = new CarViewModel();
ko.applyBindings(car);
&lt;/pre&gt;
&lt;br /&gt;
Ну и рабочий пример.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/z2JPg/1/embedded/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
Тут ничего военного не появилось, все тот же &lt;b&gt;init&lt;/b&gt; и &lt;b&gt;update&lt;/b&gt;. В инит находится код, который я полностью скопировал с ответа на stackoverflow.&lt;br /&gt;
Если вы посмотрите на html, то увидите там строчку&lt;b&gt;:&lt;span class=&quot;xml-attname&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class=&quot;xml-attname&quot;&gt;data-bind&lt;/span&gt;&lt;span class=&quot;xml-punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;xml-attribute&quot;&gt;&quot;value: Age, inputFilter: &#39;Numbers&#39;&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;
&lt;br /&gt;
Это значит что мы хотим связать наш инпут со значением поля Age и добавляем наш кастомный биндинг с параметром &lt;b&gt;Numbers&lt;/b&gt;.&lt;br /&gt;
Когда вызывается метод &lt;b&gt;init&lt;/b&gt; мы получаем значение, которое передали в &lt;b&gt;inputFilter&lt;/b&gt;, в данном случае это будет &lt;b&gt;&#39;Numbers&#39;&lt;/b&gt;. Это значение получается в данной строке&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class=&quot;js-keyword&quot;&gt;var &lt;/span&gt;&lt;span class=&quot;js-variabledef&quot;&gt;filter &lt;/span&gt;&lt;span class=&quot;js-operator&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;js-variable&quot;&gt;ko&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-property&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;js-property&quot;&gt;unwrapObservable&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-localvariable&quot;&gt;valueAccessor&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;js-punctuation&quot;&gt;;&lt;/span&gt;&lt;/b&gt;&lt;span class=&quot;xml-attribute&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
ну а дальше все ясно вроде, если это Number цепляем обработчик. &lt;br /&gt;
В данном случае, нам не нужен update, нам достаточно прицепить обработчик &lt;b&gt;keydown&lt;/b&gt; один раз в &lt;b&gt;init&lt;/b&gt; и все, потом он будет жить своей жизнью.&lt;br /&gt;
&lt;br /&gt;
Помоему получилось красиво!&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Что можно сделать лучше:&lt;/u&gt;&lt;br /&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Код, который у меня находится в &lt;b&gt;init&lt;/b&gt; можно вынести в плагин jquery или просто найти готовый плагин, ссылки на них есть в тоже же ответе.&lt;/li&gt;
&lt;li&gt;Можно ввести в дело еще один параметр например &lt;b&gt;Characters&lt;/b&gt; и фитровать только по буквам.&lt;/li&gt;
&lt;li&gt;Можно пойти дальше и передавать допустимые символы, например !&quot;№;%@ или еще лучше принимать шаблон. Я думаю изобретать парсер шаблона не придется, есть jquery плагины, досточно будет просто принять шаблон через &lt;b&gt;custom binding.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
Вопросы приветствуются. &lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/1557007687387900397/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2012/07/knockout.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/1557007687387900397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/1557007687387900397'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2012/07/knockout.html' title='Ограничиваем ввод только цифрами с помощью кастомного биндинга Knockout'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-2988084000816917813</id><published>2012-07-04T00:41:00.000+03:00</published><updated>2012-07-11T13:39:05.705+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Code Generation"/><category scheme="http://www.blogger.com/atom/ns#" term="Tools"/><category scheme="http://www.blogger.com/atom/ns#" term="XML"/><category scheme="http://www.blogger.com/atom/ns#" term="XSD"/><title type='text'>Генерация классов из XSD файлов с помощью Xsd2Code.</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Недавно я интегрировался с веб сервисами компании &lt;a href=&quot;http://www.verizonwireless.com/&quot; target=&quot;_blank&quot;&gt;Verizon&lt;/a&gt;. Общение с версисом происходило через XML с определенной структорой. В общем, запрос представлял из себя шапку (header) и сам запрос (body). Пример:

&lt;br /&gt;
&lt;pre class=&quot;brush: xml; gutter: true;&quot;&gt;&lt;posbizservices&gt;
  &lt;posbizserviceheader&gt;
    &lt;userid&gt;*****&lt;/userid&gt;
    &lt;password&gt;********&lt;/password&gt;
    &lt;clientid&gt;**&lt;/clientid&gt;
    &lt;action&gt;MISC&lt;/action&gt;
    &lt;responseformat&gt;XML&lt;/responseformat&gt;
  &lt;/posbizserviceheader&gt;
  &lt;request&gt;
    &lt;miscrequest&gt;
      &lt;ecpdid&gt;******&lt;/ecpdid&gt;
      &lt;devicelookup&gt;
        &lt;devicebrand&gt;HTC&lt;/devicebrand&gt;
      &lt;/devicelookup&gt;
    &lt;/miscrequest&gt;
  &lt;/request&gt;
&lt;/posbizservices&gt;
&lt;/pre&gt;
&lt;br /&gt;
В документации были только примеры XML запросов и ответов для каждого типа запроса, например активация линии, информация о немере, смена тарифного плана и тп. В основном сохранялся только тег request, а внутри него менялся контет. &lt;br /&gt;
Сначала я эти запросы формировал руками через XLinq и это было совсем не круто. Потом компания предоставила XSD файлы для каждого запроса и сказала, что мы можем использовать эти файлы для генерации XML запросов. До этого с XSD никогда не сталкивался и пока не нагуглил не знал как оно мне поможет.&lt;br /&gt;
&lt;br /&gt;
В общем помогают эти файлы следующим образом:&lt;br /&gt;
1. Cначала с помощью одной из утилит &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=vs.100%29.aspx&quot;&gt;XSD.exe&lt;/a&gt; от Microsoft или &lt;a href=&quot;http://xsd2code.codeplex.com/&quot;&gt;Xsd2Code&lt;/a&gt; на codeplex, можно сгенерить cs или vb файлы.&lt;br /&gt;
2. Код в этих файлах будет сгенерен с Xml аттрибутами, необхадимыми для формаирования правильного XML запроса. Чтоб сгенерить Xml, который я показал в примере, используется &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx&quot;&gt;XmlSerializer&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
Так в 2 шага можно сгенерировать валидный XML по XSD файлам.&lt;br /&gt;
Когда я дошел до генерации CS файлов из XSD, то выбора было не особо та и примеров как это делать тоже, в основном ссылки на xsd.exe с которым я так и не подружился. &lt;br /&gt;
В данной статье я хотел рассказать об утилите Xsd2Code.Чем она хороша ?&lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Очень много настроек&lt;/li&gt;
&lt;li&gt;Интегрируется с студией&lt;/li&gt;
&lt;li&gt;Понимает теги xsd:include, которые ссылаются на другие xsd файлы. &lt;/li&gt;
&lt;li&gt;Не сложная в использовании&lt;/li&gt;
&lt;/ol&gt;
Как использовать ?&lt;br /&gt;
&lt;br /&gt;
Для начала скачать и установить.&lt;br /&gt;
&lt;br /&gt;
Дальше вызвав в консоли Xsd2Code.exe можно увидеть список доступных параметров&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text; gutter: true;&quot;&gt;Usage: 

    Xsd2Code.exe &lt;xsd file=&quot;&quot;&gt; [Namespace] [Output file name] [Options]

Where:
    &lt;xsd file=&quot;&quot;&gt;                          - Path to an XSD file. Required
    [Namespace]                         - Generated code namespace. Optional. File name without extension if no value is specified
    [Output file name]                  - Name of the output (generated) file. Optional. 
    [Options]                           - Optional. See below for description

Options:
    /o[utput] &lt;filename&gt;                - Name of the output (generated) file. 
                                          By default, name of the source file with extension .Designer.cs 
                                          (.Designer.vb or .Designer.cpp for VisualVasic and Visual C++ respectively)
    /n[s] &lt;namespace&gt;                   - Generated code CLR namespace. Default: file name without extension
    /l[anguage] &lt;language&gt;              - Generated code language (CS|VB|CPP). Default: CS
    /pl[atform] &lt;platform&gt;              - Generated code target platform (Net20|Net30|Net35|Silverlight20). Default: Net20
    /c[ollection] &lt;collection base=&quot;&quot;&gt;     - Collection base (Array|BindingList|List|ObservableCollection|DefinedType). Default: List
    /cu[customusings] &lt;custom usings=&quot;&quot;&gt;   - Comma-separated of custom usings definition (E.g &quot;Xsd2Code.Library,System.Xml.Linq&quot;)
    /sm &lt;serialize&gt;                     - Serialize method name. Default: Serialize
    /dm &lt;deserialize&gt;                   - Deserialize method name. Default: Deserialize
    /lf[m] &lt;loadfromfile&gt;               - LoadFromFile method name. Default: LoadFromFile
    /sf[m] &lt;savetofile&gt;                 - SaveToFile methodname. Default: SaveToFile
    /is[+]                              - Include Serialize method
    /is-                                - Do not include Serialize method (default)
    /cl[+]                              - Include Clone method
    /cl-                                - Do not include Clone method (default)
&lt;/pre&gt;
&lt;br /&gt;
Это не полный список, их раза в 2-3 больше, но нам все не надо.&lt;br /&gt;
&lt;br /&gt;
Дальше генерим CS файл из XSD. Пример:&lt;/div&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;b&gt;Xsd2Code.exe POSBizCheckStatus.xsd Ivanov.VerizonIntegration C:\POSBizCheckStatus.cs /pl Net35 /c Array /xa /is /sс &lt;/b&gt;&lt;/div&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;b&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;/div&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
По порядку:&lt;br /&gt;
&lt;b&gt;Xsd2Code.exe - &lt;/b&gt;путь к файлу или если вы находитесь в папке с утилитой, то просто название запускаемого файла утилиты.&lt;br /&gt;
&lt;b&gt;POSBizCheckStatus.xsd - &lt;/b&gt;путь к xsd файлу или если он находится в папке с утилитой то просто нзвание файла. &lt;u&gt;Вайжно!!! Лучше чтоб путь к xsd файлу не содержал пробелы, а то может не сработать &lt;/u&gt;&lt;br /&gt;
&amp;nbsp;&lt;b&gt;Ivanov.VerizonIntegration - &lt;/b&gt;namespace в котором будет сгенерированый класс.&lt;br /&gt;
&lt;b&gt;C:\POSBizCheckStatus.cs - &lt;/b&gt;путь и название cs файла в котором будет сгенереный класс по XSD схеме.&lt;br /&gt;
&lt;b&gt;/pl &lt;/b&gt;&lt;b&gt;Net35&lt;/b&gt;&lt;b&gt; - &lt;/b&gt;версия .NET для кода в данном случае 3.5&lt;br /&gt;
&lt;b&gt; /c Array - &lt;/b&gt;как мы хотим видеть колекции, на выбоор несколько опций, в моем случае хочу чтоб колекции были как обычные массивы.&lt;br /&gt;
&lt;b&gt;/xa - &lt;/b&gt;именно с этой опцией добавляются xml аттрибуты, которые помогу XmlSerializer&#39;у правилно сгенерировать XML. Эту опцию можно отключить. Пример&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; gutter: true;&quot;&gt;    [GeneratedCode(&quot;Xsd2Code&quot;, &quot;3.4.0.38968&quot;)]
    [Serializable]
    [DesignerCategory(&quot;code&quot;)]
    [XmlType(AnonymousType = true, Namespace = &quot;http://pos.odc.vzwcorp.com&quot;)]
    public class miscResponseAccessoryList
    {
        private static XmlSerializer serializer;
        private miscResponseAccessoryListAccessoryInfo[] accessoryInfoField;
        private string countField;

        [XmlElement(DataType = &quot;integer&quot;, Order = 0)]
        public string count
        {
            get { return countField; }
            set { countField = value; }
        }

        [XmlElement(&quot;accessoryInfo&quot;, Order = 1)]
        public miscResponseAccessoryListAccessoryInfo[] accessoryInfo
        {
            get { return accessoryInfoField; }
            set { accessoryInfoField = value; }
        }
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;/is&lt;/b&gt; - этот ключ добавляет в файл метод Serialize / Deserialize. Очень удобно, самому уже не надо писать.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; gutter: true;&quot;&gt; 
public virtual string Serialize()
        {
            StreamReader streamReader = null;
            MemoryStream memoryStream = null;
            try
            {
                memoryStream = new MemoryStream();
                Serializer.Serialize(memoryStream, this);
                memoryStream.Seek(0, SeekOrigin.Begin);
                streamReader = new StreamReader(memoryStream);
                return streamReader.ReadToEnd();
            }
            finally
            {
                if ((streamReader != null))
                {
                    streamReader.Dispose();
                }
                if ((memoryStream != null))
                {
                    memoryStream.Dispose();
                }
            }
        }
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;/sc&amp;nbsp; - &lt;/b&gt;добавляет коментарии к свойствам.&lt;br /&gt;
&lt;br /&gt;
Остальные ключи добавляются по мере необходимости. Есть настроки для WCF, Linq, DataBinding и тп.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у вас несколько XSD файлов и для них всех нужно сгенерить классы, например как у меня&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW4na6eGaP1kmSHxrSNCKJNCxl-6VOt1ANN2s5l_XnsRB9ONNB_1CBH_l28ABCMr8kHn3ekPEmbv7BRtgW7n_WDL-HHSCFgtMId034zcTtZQvoY4kzPp_6UrNnOV3BU8LXbeiUqfqkQjk/s1600/2012-07-04_0025.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW4na6eGaP1kmSHxrSNCKJNCxl-6VOt1ANN2s5l_XnsRB9ONNB_1CBH_l28ABCMr8kHn3ekPEmbv7BRtgW7n_WDL-HHSCFgtMId034zcTtZQvoY4kzPp_6UrNnOV3BU8LXbeiUqfqkQjk/s1600/2012-07-04_0025.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
то можно использовать bat файл.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text; gutter: true;&quot;&gt;
@echo off

set XsdPath=&quot;c:\Path\To\Xsd\Files&quot;
set OutPath=%XsdPath%\Code
set ExePath=&quot;c:\Program Files (x86)\Xsd2Code\&quot;
set Namespace=MyProject.Namespace
echo.Starting processing XSD files ...
for /f %%a IN (&#39;dir %XsdPath%\*.xsd /a-d /b /s&#39;) do call:ProcessXsd %%a

echo.Finished processing XSD files ...
echo.&amp;amp;pause&amp;amp;
goto:eof

:ProcessXsd
%ExePath%\Xsd2Code %~1 %Namespace% %XsdPath%\Code\%~n1%.cs /pl Net35 /c Array /xa /is
echo.Processed %~n1
goto:eof
&lt;/pre&gt;
&lt;br /&gt;
Нужно подставить значение XsdPath, OutPath, ExePath и Namespace. В моем случае я получил список файлов в папке Code.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim_TGTItTvlT1Et5euVYcTSoct-5JAzfD3z4NtNVhVxWCngIEAGSHZuE67m9kBO9G9R3Jsgq-8K-9RBoMpSz5PGu4c7ieUNdlLYa97NAQZbDDl6lBHXWkt2vBhBCnT17cecpa5_IpNudw/s1600/2012-07-04_0031.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim_TGTItTvlT1Et5euVYcTSoct-5JAzfD3z4NtNVhVxWCngIEAGSHZuE67m9kBO9G9R3Jsgq-8K-9RBoMpSz5PGu4c7ieUNdlLYa97NAQZbDDl6lBHXWkt2vBhBCnT17cecpa5_IpNudw/s1600/2012-07-04_0031.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Это важно!&lt;/b&gt; &lt;br /&gt;
&lt;i&gt;&lt;u&gt;OutPath папка должна существовать, иначе провал. &lt;/u&gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;u&gt;XsdPath путь не должен содержать пробелов, иначе тоже пробвал&lt;/u&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Пример использования в коде&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; gutter: true;&quot;&gt;logger.Info(&quot;Building XML for REASSIGN ACCOUNT request.&quot;);

            POSBizServices requestMessage = serviceRequestFactory.CreateReassignAccountRequest(request);

            logger.Info(&quot;Sending REASSIGN ACCOUNT request.&quot;);

            string requestXml = requestMessage.Serialize();
            string responseXml = SendRequest(requestXml);

            logger.Debug(&quot;REASSIGN ACCOUNT response: {0}.&quot;, responseXml);

            POSBizServices responseMessage;

            try
            {
                logger.Info(&quot;Deserializing XML response to POSBizServices as LINE STATUS response.&quot;);
                POSBizServices.Deserialize(responseXml, out responseMessage);
            }
            catch (Exception e)
            {
                logger.ErrorException(&quot;Error while deserializing LINE STATUS XML response to POSBizServices&quot;, e);
                throw;
            }
&lt;/pre&gt;
&lt;br /&gt;
Пользуйтесь! Будут вопросы - отвечу.
&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/2988084000816917813/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2012/07/xsd-xsd2code.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/2988084000816917813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/2988084000816917813'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2012/07/xsd-xsd2code.html' title='Генерация классов из XSD файлов с помощью Xsd2Code.'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW4na6eGaP1kmSHxrSNCKJNCxl-6VOt1ANN2s5l_XnsRB9ONNB_1CBH_l28ABCMr8kHn3ekPEmbv7BRtgW7n_WDL-HHSCFgtMId034zcTtZQvoY4kzPp_6UrNnOV3BU8LXbeiUqfqkQjk/s72-c/2012-07-04_0025.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-4096607363670225962</id><published>2012-01-23T16:08:00.003+02:00</published><updated>2013-05-27T19:12:22.566+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="jQuery"/><category scheme="http://www.blogger.com/atom/ns#" term="Knockout"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="UI"/><title type='text'>Цепляем jQuery Datepicker c помощью кастомного биндинга на KnockoutJS</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Как я говорил в &lt;a href=&quot;http://delmadman.blogspot.com/2012/01/javascript-c-knockoutjs.html&quot;&gt;предыдущей статье&lt;/a&gt; сегодня мы создадим свою &quot;команду&quot; ну или правильному &lt;a href=&quot;http://knockoutjs.com/documentation/custom-bindings.html&quot; target=&quot;_blank&quot;&gt;custom binding&lt;/a&gt; (кастомный биндинг).&lt;br /&gt;
Что это такое ?&lt;br /&gt;
В knockout для того, чтобы с вашим элементом происходили какие-то махинации: скрыть, сделать неактивным, добавить стиль, присвоить значение и тп существуют команды, некоторые из которых вы уже видели в примерах - value, text, visible, ckecked, enable, options. Эти команды предопределены в фреймворке и предоставляют базовый и достаточный функционал для реализации ваших нужд.&lt;br /&gt;
Иногда бывают случаи когда код выглядит когда их вроде бы не хватает. Например, обавим в наши фильтры поддержку типа &lt;b&gt;Date&lt;/b&gt; и когда пользователь выбрал поле, например &lt;b&gt;Issue Date&lt;/b&gt;, установил курсор чтоб ввести значение, я хочу чтоб он не вводил его руками, а выбрал дату через &lt;a href=&quot;http://jqueryui.com/demos/datepicker/&quot; target=&quot;_blank&quot;&gt;jQuery datepicker&lt;/a&gt;. Естественно я хочу чтоб выбор даты срабатывал только для Date типа фильров, а для других Number и String оставался просто полем ввода.&lt;br /&gt;
Без своей кастомной команды, нам бы пришлось подписаться через subscribe на &lt;span class=&quot;js-property&quot;&gt;ColumnObj и смотреть при выборе поля из выпадающего списка его тип. Если это дата - применить datepicker, если нет - удалить datepicker. Если мы в будущем захотим добавить еще какую-то логику, то пойдут кастыли и будет все в куче.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;js-property&quot;&gt;Тут нам как раз и поможет кастомный биндинг (команда). В итоге наш шаблон будет выглядеть так:&lt;/span&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: html; gutter: false;&quot;&gt; 
    &amp;lt;input data-bind=&quot;value: Value, datePicker: Type&quot; type=&quot;text&quot; /&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Вся логика для выбора даты будет вынесена в команду &lt;b&gt;datePicker&lt;/b&gt;. Собственно код:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript: gutter: false;&quot;&gt;ko.bindingHandlers.datePicker = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var type = ko.utils.unwrapObservable(valueAccessor());

        if (type == &#39;Date&#39;) {
            $(element).datepicker();
        }

    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var type = ko.utils.unwrapObservable(valueAccessor());

        if (type == &#39;Date&#39;) {
            $(element).datepicker();
        }
        else {
            $(element).datepicker(&quot;destroy&quot;);
        }
    }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Я не буду описывать все опции в деталях, о них выможете прочитать &lt;a href=&quot;http://knockoutjs.com/documentation/custom-bindings.html&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;.&lt;br /&gt;
Рассмотром, что и как.&amp;nbsp; Как мы видим для того чтобы создать команду, мы создаем объект с соответствующим называнием команды в &lt;b&gt;ko.bindingHandlers&lt;/b&gt;. У нашего объекта должно быть две функции.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;init &lt;/b&gt;- вызывается, когда knockout доходит до места в html, где установленна наша команда.&lt;br /&gt;
&lt;b&gt;update &lt;/b&gt;- вызывается, когда изменится значение поля за которым мы следим с помощью нащей команды.&lt;br /&gt;
В нашем случае, &lt;b&gt;data-bind=&quot;dataPicker: Type, &lt;span class=&quot;xml-attribute&quot;&gt;value: Value&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&quot;&lt;/b&gt; значит - следить за полем &lt;b&gt;Type&lt;/b&gt; и если оно изменится вызвать команду &lt;b&gt;datePicker&lt;/b&gt;. Она вызовится при инициализации и после последющих обновлений.&lt;br /&gt;
Что происходит в обработчиках?&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;valueAccessor()&lt;/b&gt; - возвращает поле, к которому привязана команд. Это всегда будет функция. т.к. все поля объявляются через ko.obsorvable или ko.computed и они возврашают функции. &lt;br /&gt;
&lt;b&gt;ko.utils.unwrapObservable&lt;/b&gt; - это функция, которая вычисляет значение поля на такущий момент, когда вызывается эта строка. &lt;br /&gt;
Дальше, я думаю, все понятно. Параметры, которые передаютися в init и update очевидны, кроме &lt;b&gt;&lt;code&gt;allBindingsAccessor&lt;/code&gt;, &lt;/b&gt;но и пользоваться им вы врядли будете.&lt;br /&gt;
&lt;br /&gt;
Ниже рабочий пример. Я добавил тип Date в Conditions, саму команду datePicker и поле Issue Date.&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/75fA3/15/embedded/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/4096607363670225962/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2012/01/jquery-datepicker-c-knockoutjs.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4096607363670225962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4096607363670225962'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2012/01/jquery-datepicker-c-knockoutjs.html' title='Цепляем jQuery Datepicker c помощью кастомного биндинга на KnockoutJS'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-3057025627880993211</id><published>2012-01-13T19:06:00.001+02:00</published><updated>2013-05-27T19:08:33.914+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Knockout"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="UI"/><title type='text'>Динамические фильтры на Javascript c помощью KnockoutJS</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Сегодня я покажу практический пример, как можно применить &lt;a href=&quot;http://knockoutjs.com/&quot; target=&quot;_blank&quot;&gt;KnockoutJS&lt;/a&gt; в реальном проекте и сделаем мы динамические фильтры для поиска задач, багов, тасков и тп по разработчику, названию таска и описанию. Возможно вы такие уже видели в TFS для генерации отчета или других системах, где можно добавлять любые фильтры и условия для поиска чего-либо. В итоге выглядит это так:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/vWg97/16/embedded/result,js,html/presentation/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
В конце мы добавим валидацию, чтоб нельзя было добавлять фильтр, если текущий пустой, а в следующей статье я напишу о том как можно писать плагины и свои команды в knockout и добавит фильтр по дате.&lt;br /&gt;
&lt;br /&gt;
Приступим!&lt;br /&gt;
&lt;br /&gt;
Сначала&amp;nbsp; определимся, что будет представлять из себя сам фильтр:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Column &lt;/b&gt;- колонка по кторой фильтруем или ищем&lt;br /&gt;
&lt;b&gt;Condition &lt;/b&gt;- оператор для фильтра =, != и тп&lt;br /&gt;
&lt;b&gt;Value &lt;/b&gt;- значение фильтра&lt;br /&gt;
&lt;b&gt;Type &lt;/b&gt;- тип. Пока что у нас будет только String, Number потом расширим&lt;br /&gt;
&lt;b&gt;NextFilterBinaryCondition &lt;/b&gt;- это условие с которым будет выполняться следующий фильтр &quot;И&quot;, &quot;ИЛИ&quot;. Например Developer = &quot;Vitaly&quot; and Issue = &quot;write post&quot; or Issue Description = &quot;knockout&quot;.&lt;br /&gt;
&lt;br /&gt;
Фильтры у нас будуте создаваться по названию поля по которому мы фильтруем. Колонки у нас хранятся как объекты. При создании фильтра мы сохраним название поля и найдем в списке объект колонку с помощью вспомогательной функции findFilterColumn и будем хранить обьъект колонка в поле ColumnObj.&amp;nbsp; &lt;br /&gt;
Если поле ColumnObj изменится, мы очищаем значение фильтра. Чтоб следить за изменениями поля ColumnObj мы подписуемся функцией &lt;b&gt;subscribe&lt;/b&gt;.&lt;br /&gt;
Функцию-оброботчик, которыю мы передаем в &lt;b&gt;subscribe, &lt;/b&gt;будет вызываться всегда, когда значение поля, на которое мы подписываемся, изменится.&lt;br /&gt;
Все поля, кроме &lt;b&gt;ColumnObj, Condition, Value, NextFilterBinaryCondition&lt;/b&gt;&amp;nbsp; зависымые и значения мы не присваиваем им явно. Значения для этих полей пересчитываются при любом изменения одного из обычных полей. Это одна из прелестей knockout! Если смотреть сверху вниз то экосистема knockout будет вызывать обработчики в следующем порядке:&lt;br /&gt;
1. Присвоить значение в ColumnObj&lt;br /&gt;
2. Определеить поле Column как зависимое и попробовать просчитать.&lt;br /&gt;
3. Присвоить значение полю Condition.&lt;br /&gt;
4. Пересчитать Column&lt;br /&gt;
5. Присвоить значение полю NextFilterBinaryCondition.&lt;br /&gt;
6. Пересчитать Column.&lt;br /&gt;
7. Определеить поле Type как зависимое и просчитать.&lt;br /&gt;
8. Пересчитать Column. &lt;br /&gt;
9.&amp;nbsp;Определеить поле AvailableConditions как зависимое и просчитать.&lt;br /&gt;
10. Пересчитать Type.&lt;br /&gt;
11. Пересчитать Column.&lt;br /&gt;
12. Установить значние поля Value и пересчитать Column, Type, AvailableConditions.&lt;br /&gt;
&lt;br /&gt;
Все поля устанавливаются и пересчитываются по порядку в котором они были объявлены.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрит класс, который управляет всей бизнес логикой, хранит фильтры и он является и называется &lt;b&gt;ViewModel&lt;/b&gt;&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/Bna2w/1/embedded/js/presentation/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
Объект &lt;b&gt;Conditions&lt;/b&gt; содержит список типов фильтров и соответсвенно операций, условий, которые мы поодерживаем для этих типов данных. Также есть вспомогательная функция для поиска доступных условий по названию типа.&lt;br /&gt;
&lt;br /&gt;
Например найти все доступные условия для фильтрации по типо &#39;Number&#39;. Этой функцией мы будем пользоваться когда после выбора поля в первом списке, нам нужно будет отобразаить доступные условия во втором выпадающем списке.&lt;br /&gt;
&lt;br /&gt;
Небольшое ТЗ. У нас должны выполнятся следующие требования:&lt;br /&gt;
- хранить фильтры&lt;br /&gt;
- добавлять фильтры&lt;br /&gt;
- удалять фильтры&lt;br /&gt;
- посылать все фильтры на сервер&lt;br /&gt;
&lt;br /&gt;
При создании ViewModel мы передаем в него список колонок, которы объявлены выше. В конструкторе мы создаем массив фильтров и сразу добавляем один пустой фильтр. Если этого не сделать, то у нас на экране будет одна кнопка. Как только мы добавляем пустой фильтр, экосистема knockout трекает это, уведомляет всех подписчиков на изменения, если есть такие, и отображает пустой добавленные фильтр по шаблону и определенной для него бизнес логике.&lt;br /&gt;
&lt;br /&gt;
Функция &lt;b&gt;addFilter&lt;/b&gt; принимает объект фильтр, напротив которого мы клацнули &quot;+&quot;, находит этот фильтр в списке уже существующих фильтров и добавляет после него новый пустой.&lt;br /&gt;
В данном случае у нас нет проверки, заполнены ли все фильтры или нет. Сейчас мы можем нажимать &quot;+&quot; бесконечно и у нас будет куча фильтров. Мы это исправим потом.&lt;br /&gt;
&lt;br /&gt;
Функция &lt;b&gt;removeFilter&lt;/b&gt; принимает объект фильтры который надо удалить, удаляет его из списка фильтров и если это был последний фильтр мы добавляем пустой. Зачем? Если мы этого не сделаем, то мы не сможем добавить фильтры, т.к. &quot;+&quot; отображается на строке с фильтром и без него у нас останется только кнопка &lt;b&gt;submit&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Функция &lt;b&gt;postFilters&lt;/b&gt; показывает сообщение с сериализованными фильтрами в JSON, которые надо послать на сервер для обработки. В knockout есть много утилитных функций о которых мы можете почитать подробней &lt;a href=&quot;http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Функция &lt;b&gt;toJS&lt;/b&gt;, создает новый js объект, который не связан больше с knockout, это просто js объект. Все свойства в нем будут вычеслены с теми значениями, которые были на момент вызова функции toJS.&lt;br /&gt;
&lt;br /&gt;
Когда мы сериализовали фильтры в js objects, то там будут поля, которые нам нужны и которые были нужны только для knockout, например &lt;b&gt;ColumnObj, AvailableConditions&lt;/b&gt;. Эти поля не несут нам никакой информации на сервере, поэтому мы их смело удаляем и на сервер пойдет меньше данных. Функция toJSON сериализует js класс в JSON строку, которую мы и показываем.&lt;br /&gt;
&lt;br /&gt;
Переходим к рассмотрению шаблона html:&lt;br /&gt;
&lt;br /&gt;
Фильтры отображаются по шаблону в данном случае шаблон, это li и все что внутри него.&lt;br /&gt;
В предыдущих версия knockout обязательно надо было подключать jQuery Teample. В последней версии этого делать больше не нужно, теперь в фреймворке есть свой встроеный движок для шаблонов со своими плюшками. О всех новшествах новой версии 2.0 можно прочитать на блоге самого разработчика &lt;a href=&quot;http://blog.stevensanderson.com/2011/12/21/knockout-2-0-0-released/&quot; target=&quot;_blank&quot;&gt;здесь.&lt;/a&gt;&lt;br /&gt;
Из нового&amp;nbsp; я использую переменную &lt;b&gt;$root&lt;/b&gt;, которая ссылается на ViewModel класс. Если этого не сделать, то, например, поле &lt;b&gt;columns&lt;/b&gt; будет искаться в классе &lt;b&gt;Filter&lt;/b&gt;. Команда &lt;b&gt;foreach&lt;/b&gt; пробегает по всем объектам коллекции &lt;b&gt;filters&lt;/b&gt; и применяет шаблон для каждого объекта Filter. &lt;u&gt;Шаблон выполняется с контекстом объекта&lt;/u&gt;, который передается в шаблон (Filter).&lt;br /&gt;
Переменная &lt;b&gt;$data &lt;/b&gt;хранит ссылку на объект контекста (Filter в данном случае). Этой переменной я воспользовался, когда добавлял или удалял фильтр.&lt;br /&gt;
По умолчанию функции вызываются в контексте объекта в шаблоне (Filter), для этого в новой версии не нужно писать function () { ... }, есть более красиывый синтаксис например click: removeFilter($data). Но нам надо выполнять функции в контексте ViewModel поэтому мы пишем по старому, через function и выполняем функцию в контексте, котором нам надо.&lt;br /&gt;
&lt;br /&gt;
Вроде бы все.&lt;br /&gt;
&lt;br /&gt;
Теперь, как я говорил, добавим проверку. Если у нас хотя бы один фильтр без значения, то мы не будем добавлять новый.&lt;br /&gt;
Обновленный класс ViewModel выглядит теперь так:&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/ZqX73/3/embedded/js/presentation/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt; 
&lt;br /&gt;
а фильтр так: &lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/75fA3/14/embedded/js/presentation/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt;
&lt;br /&gt;
и собственно результат:
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/75fA3/14/embedded/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
В следующей статье я напишу как писать расширения для knockout и мы сделаем фильтр по дате. Если у нас поле будет с типом Date, то к нему будет автоматически применяться jQuery date picker.&lt;br /&gt;
&lt;br /&gt;
Вопросы, коментарии преветсвуются!&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/3057025627880993211/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2012/01/javascript-c-knockoutjs.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/3057025627880993211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/3057025627880993211'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2012/01/javascript-c-knockoutjs.html' title='Динамические фильтры на Javascript c помощью KnockoutJS'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-6354113651718903157</id><published>2011-12-22T18:49:00.001+02:00</published><updated>2011-12-22T19:11:03.140+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC 3"/><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Performance"/><title type='text'>Отображение картинки из базы без запроса на сервер в MVС</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Я искал альтернативный способ как можно отобразить картинку на странице не делая запроса на сервер, который отдает контент изображения. В основном, у всех вывод картинки на страницу выглядит так:&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;http://i54.tinypic.com/1h82m8.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i54.tinypic.com/1h82m8.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
если она у вас хранится на диске то первый варинат, если в базе то второй вариант. В обоих случая браузер посылает GET запрос на картинку. Если мы отображаем 10 записей, мы должны сделать 10 запросов чтоб получить картинки. А если мы делаем фотоальбом, отображаем штук 30 привьюх и храним картинки в базе, то грузиться будет дольше.&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Решение которое я покажу называется &lt;a href=&quot;http://www.websiteoptimization.com/speed/tweak/inline-images/&quot; target=&quot;_blank&quot;&gt;inline image&lt;/a&gt;. Суть в том, что вы не делаете лишний запрос за картинкой, вы сразу встраиваете картинку в браузер. Выглядит это так&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: justify;&quot;&gt;
&lt;a href=&quot;http://i51.tinypic.com/2n0iohv.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i51.tinypic.com/2n0iohv.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
В src просто пишется контет, закодированый через base64. Так выглядит мой хелпер, который может генерит такую картинку.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; gutter: true;&quot;&gt; public static class ImageHelper
    {
        public static MvcHtmlString Image(this HtmlHelper html, byte[] imageBytes, string mime, object attributes)
         {
             TagBuilder img = new TagBuilder(&quot;img&quot;);

             StringBuilder sb = new StringBuilder();
             sb.AppendFormat(&quot;data:{0};&quot;, mime);
             sb.AppendFormat(&quot;base64,{0}&quot;, Convert.ToBase64String(imageBytes));

             img.MergeAttribute(&quot;src&quot;, sb.ToString());

             return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
         }
    }

    // пример использование
    @Html.Image(Model.ToArray(), &quot;image/jpg&quot;, new { width = 530, height = 390 })&amp;nbsp;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Конечно для картинок которые весяк около 30kb, src будет намного больше. Например чтоб отобразить такой значок в 35kb&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh563l3XfoeoNx2QdRr7RVPFoBBfBz9v9-Q3qzT1jE-knTlbDtz3hOMu02i57L1X7QxLXekaBVSZvsRDxWFw2a-FLVuCGzmQA27YkT20f1dnGTTeI9Yzs5B8eTXRiPwj3ALqzCZecS0QWA/s1600/subaru_logo_small.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh563l3XfoeoNx2QdRr7RVPFoBBfBz9v9-Q3qzT1jE-knTlbDtz3hOMu02i57L1X7QxLXekaBVSZvsRDxWFw2a-FLVuCGzmQA27YkT20f1dnGTTeI9Yzs5B8eTXRiPwj3ALqzCZecS0QWA/s1600/subaru_logo_small.jpg&quot; /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
у меня получилось&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i51.tinypic.com/2c0dp5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i51.tinypic.com/2c0dp5.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
 &lt;br /&gt;токо шире в 4 раза :)&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Итог&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Преимущества данного решения в том, что мы избавляемся от лишнего запроса на сервер и если размер картинки не велик, например, до 10 кб, то данное решение будет оптимально для отображения кучи картинок, если они у вас хранятся в байтах.&lt;br /&gt;
Конечно у него есть и недостатки: что мне очень не нравится, то что картинки не кэшируются :/ (только если всунуть data в css) и эта возможность не поддерживается некоторыми версиями браузеров.&lt;br /&gt;
&lt;br /&gt;
В общем это было алтернативное решение, которое имеет место жить в частных случаях. Часто такое можно увидеть в css если посмотреть сайты yahoo, youtube, amazon и тп.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/6354113651718903157/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2011/12/mv.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/6354113651718903157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/6354113651718903157'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2011/12/mv.html' title='Отображение картинки из базы без запроса на сервер в MVС'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://i54.tinypic.com/1h82m8_th.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-5220314858130433873</id><published>2011-12-20T19:27:00.001+02:00</published><updated>2011-12-21T12:50:15.069+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET MVC 3"/><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio"/><title type='text'>Настройка проекта для прекомпиляции cshtml файлов в ASP MVC 3</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Если вы писали на ASP MVC 3, то наверно сталкивались с проблемой, что ошибки во вью файлах не отображаются при компиляции проекта, их нет в Error List. Об ошибках вы можете узнать только если переклацаете весь проект :) Это происходит потому, что Razor вьюхи не компилируются когда вы билдите проект в студии.&lt;br /&gt;
Можно сделать, чтоб вьюхи компилировались и ошибки во вьюхах отображались в Error List.&lt;br /&gt;
&lt;br /&gt;
Механика:&lt;br /&gt;
&amp;nbsp;Открываем файл проекта в блокноте, находим в первой &lt;b&gt;Project Group&lt;/b&gt; секции тег &lt;b&gt;MvcBuildViews&lt;/b&gt; и меняем значение c &lt;b&gt;&lt;mvcbuildviews&gt;false&lt;/mvcbuildviews&gt;&lt;/b&gt; на &lt;b&gt;true &lt;/b&gt; и воаля!.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i52.tinypic.com/70ystd.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;br /&gt;&lt;/a&gt;&lt;a href=&quot;http://i56.tinypic.com/amqwzp.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i56.tinypic.com/amqwzp.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i55.tinypic.com/34hudqv.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i55.tinypic.com/34hudqv.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/5220314858130433873/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2011/12/cshtml-asp-mvc-3.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/5220314858130433873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/5220314858130433873'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2011/12/cshtml-asp-mvc-3.html' title='Настройка проекта для прекомпиляции cshtml файлов в ASP MVC 3'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://i56.tinypic.com/amqwzp_th.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-305161681741009820</id><published>2011-12-11T16:10:00.001+02:00</published><updated>2013-05-27T19:00:45.214+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="jQuery"/><category scheme="http://www.blogger.com/atom/ns#" term="Knockout"/><category scheme="http://www.blogger.com/atom/ns#" term="UI"/><title type='text'>Что такое Knockout JS или MVVM на javascript. Пример</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Давно хотел написать что-то про &lt;a href=&quot;http://knockoutjs.com/&quot; target=&quot;_blank&quot;&gt;Knockout JS&lt;/a&gt; фреймворк. Если кто-то пишет сайты с интерфейсом где куча javascript, то вы найдете его для себя очень полезным, а потом не сможете без него ничего делать, т.к. к хорошему быстро привыкаешь.&lt;br /&gt;
&lt;br /&gt;
Что это такое и зачем надо ?&lt;br /&gt;
&lt;br /&gt;
Рассмотрим пример, сразу говорю выдумал на ходу, но он отображает суть.&lt;br /&gt;
Вы можете купить продукт из списка, завернуть в подарочную упаковку,&amp;nbsp; указать надпись на коробке выбрать доставку и сразу видеть цену, которая меняется от выбранных опций и Summary, которое отображает выбранные опции как результат.&lt;br /&gt;
При нажатии на &#39;Sumbit&#39; отображает JSON, которы может поститься на сервер или тп.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot; src=&quot;http://jsfiddle.net/ivanov_vitaly/gmbU4/35/embedded/result,js,html/presentation/&quot; style=&quot;height: 300px; width: 100%;&quot;&gt;&lt;/iframe&gt;

&lt;br /&gt;
Сколько бы вы делали этот пример просто на JS + jQuery ? Конечно, вы можете сказать &quot;та нехер делать&quot;, но код будет выглядеть месивом из подписывания на события, if&#39;ы для треканья зависимостей между элементами, что показать, какой скрыть, потом будете еще дэбажить, а потом начнете переосмысливать жизненные ценности и позавете Darth Vadera, чтоб он все разрулил :).&lt;br /&gt;
&lt;br /&gt;
На входе &lt;br /&gt;
&lt;br /&gt;
- Набор элементов формы (View)&lt;br /&gt;
- Данные, которые отражаются и отображаются в этих элементах (Model) и&amp;nbsp; бизнес логика, которая скрывает, отображает элементы и делает расчеты (Controller или ViewModel).&lt;br /&gt;
&lt;br /&gt;
На выходе &lt;br /&gt;
- Нужно как-то это скомпоновать, чтоб зависимости и пересчеты резолвись сами, если какое-то значение изменится и никаких явных привязок к событиям через jQuery.&lt;br /&gt;
&lt;br /&gt;
Итого, как мы видим, получается MVC, но более точно это MVVM, шаблон группы MVx, который был придуман под технологию WPF и очень хорошо укладывается с возможностями этой технологии.&lt;br /&gt;
В WPF это реализуется с помощью binding (&quot;биндинга&quot;) и класса (ViewModel) с dependency property и routed events.&lt;br /&gt;
&lt;br /&gt;
Наш ViewModel и Dependancy Property&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i55.tinypic.com/veaef7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i55.tinypic.com/veaef7.png&quot; /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp;Как мы видим у нас есть свойства, которые создаются с помощью observable. Так экоститема knockout знает, что если значение этого свойство набиндить на элемент, например, Address то это значение отобразится в текстовом поле. Если пользователь изменит значение текстового поля, новое значение запишется обратно в свойство (Address), с которым связан элемент через observable. Получается двухсторонняя связь. Можно сделать и в одну сторону, это потом.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Наш Binding&amp;nbsp; &lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; height=&quot;452&quot; src=&quot;http://i54.tinypic.com/3354b29.png&quot; width=&quot;640&quot; /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
У нас есть один атрибут &lt;b&gt;datа-bind&lt;/b&gt;, в которм мы указываем с каким свойством (значением) связывать этот элемент и дополнительные опции. Для разных элементов свойства привязываются по разному, но в общем значение datа-bind начинается так - &lt;u&gt;&quot;value: Property&quot;&lt;/u&gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим по порядку:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;select data-bind=&quot;options: Products, value: Product&quot;&lt;/b&gt; - это значит, что мы биндим список продуктов на выпадающий список и если выбранный продукт изменится, это значение запишется в свойство Product. Если бы мы указали viewModel.Product = ko.observable(&quot;Jeans&quot;) то сразу выбраными были бы &quot;Jeans&quot;.&lt;br /&gt;
&lt;b&gt;input type=&quot;radio&quot; data-bind=&quot;checked: GiftWrap&quot;&lt;/b&gt; - это значит, что мы биндим value радиокнопки на свойство GiftWrap. Какая радиокнопка выбрана - такое значение и будет &quot;Yes&quot; или &quot;No&quot;. Ничего не выбранно - значит ничего не будет, null.&lt;br /&gt;
&lt;b&gt;div data-bind=&quot;visible: GiftWrap() == &#39;Yes&#39;&quot;&lt;/b&gt; - тут начинается интересное. С помощью visible мы решаем будет ли элемент отображатся по условию после двоеточия. Если мы поставим радиокнопку в Yes, будет div style=&quot;display: none&quot;, в другом случае div style=&quot;display: block&quot;. Как это работает ? Как только одно из observable свойств меняется, экосистема knockout проверяет весь биндинг и пересчитыват условия в атрибутах.&lt;br /&gt;
С простыми свойствами я думаю несложно. Давайте рассмотрим этот кусок&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i52.tinypic.com/mimjdf.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i52.tinypic.com/mimjdf.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
и код&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://i51.tinypic.com/2s9xboj.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i51.tinypic.com/2s9xboj.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Если бы у нас было observable, мы бы не смогли посчитать Total, т. к. оно зависит от других значений свойств. Для этого мы используем новый тип свойства &lt;b&gt;dependentObservable&lt;/b&gt;, который обозначает, что это свойство считается динамически. Сколько свойств во ViewModel изменится, столько раз knockout пересчитает свойство Total. Нам остается только отобразить это свойство в &lt;b&gt;span data-bind=&quot;text: Total&quot;&lt;/b&gt;. Это все работает автоматически !!! Достаточно только поставить нужное значение и опции в атрибут data-bind. Точно также работает Summary.&lt;br /&gt;
Я не буду дальше описывать в деталях синтаксис и тп, на сайте knockout очень хорошо все расписано с отличными примерами. Моя цель была заинтересовать и показать, как можно избавиться от кучи ненужной привязки к событиям через jQuery, месива, рассредоточеной бизнес логики и других &quot;прелестей&quot; при работе с сложным UI и JS.&lt;br /&gt;
Я считают, что этот фреймворк должен быть на счету у каждого серъезного разработчика.&lt;br /&gt;
&lt;br /&gt;
Что может этот фреймворк:&lt;br /&gt;
- простой биндинг, поле-свойство&lt;br /&gt;
- сложный биндинг, динамическое значение поля&lt;br /&gt;
- можете писать свои настройки типо как value, checked и тп. &lt;br /&gt;
- можете использовать jTemplate&lt;br /&gt;
- можете использовать ajax&lt;br /&gt;
- можете биндить события, типо click, chenched и тп&lt;br /&gt;
- можете биндить не только на значение элемента, но и например явно на атрибуты или стили, например если вы хотите чтоб в style свойство color менялось если сумма больше $20 и тп.&lt;br /&gt;
- можете делать все что угодно, если мой пример отображает суть вашей проблемы.&lt;br /&gt;
&lt;br /&gt;
Мне очень нравится этот фреймворк. Читаешь доку, смотришь код и все как-то интуитивно понятно, запоминай только опции в атрибутах, а так работать одно удовольствие. Уже не раз сокращал старый код в раза полтора-два точно. Но это не главное, а главное что бизнес логика в одном месте, а вьюха в другом.&lt;br /&gt;
Есть еще подобный фреймворк &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot; target=&quot;_blank&quot;&gt;backbones&lt;/a&gt;, но мне он показался ужасным и более низкоуровневым, там надо много писать руками, очен много, но у него есть свои преимущества.&lt;br /&gt;
&lt;br /&gt;
Если вам интересна данная тема и фреймворк - напиши в коментах ваши пожелания или мысли, стоит ли мне развивать эту тему и писать другие примеры, реальные, которые я применял в проектах.&lt;br /&gt;
Отвечу на любый вопросы. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/305161681741009820/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2011/12/knockout-js.html#comment-form' title='Комментарии: 5'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/305161681741009820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/305161681741009820'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2011/12/knockout-js.html' title='Что такое Knockout JS или MVVM на javascript. Пример'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://i55.tinypic.com/veaef7_th.png" height="72" width="72"/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-6838183885875039736</id><published>2010-11-18T15:21:00.002+02:00</published><updated>2010-11-18T15:22:17.743+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AJAX"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Script Combining"/><category scheme="http://www.blogger.com/atom/ns#" term="ScriptManager"/><title type='text'>XML Parsing Error: no element found</title><content type='html'>Гугл говорит, что не только я сталкивался с такой проблемой, но причина к сожалению у каждого разная. Но в результате все видят типо:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://i53.tinypic.com/23th44g.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://i53.tinypic.com/23th44g.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;и пустой html.&lt;br /&gt;
&lt;br /&gt;
Свою ошибку вы можете посмотреть в Application_Error. У меня была &quot;The resource URL cannot be longer than 1024 characters. If using a CompositeScriptReference, reduce the number of ScriptReferences it contains, or combine them into a single static file and set the Path property to the location of it.&quot; Потому, что в в ScripMapanger\CompositeScript было много скриптов. До этого я прогнал все файлы в JSLint, но ошибок не нашел. Вот такое г..вно этот CompositeScript, лучше самому скомбинировать и перезжать на продакшен. Как-нибудь напишу решение.</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/6838183885875039736/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2010/11/xml-parsing-error-no-element-found.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/6838183885875039736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/6838183885875039736'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2010/11/xml-parsing-error-no-element-found.html' title='XML Parsing Error: no element found'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://i53.tinypic.com/23th44g_th.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-5180961933592340847</id><published>2010-10-24T14:46:00.000+03:00</published><updated>2010-10-24T14:46:58.947+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><category scheme="http://www.blogger.com/atom/ns#" term="Caching"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Performance"/><title type='text'>Как заставить браузер принудительно кэшировать картинки</title><content type='html'>Недавно сталкнулся с проблемой, когда динамически меняешь картинки жаваскриптом, то они мигают при смене первое время. Это из-за того что тратится время на загрузку по требованию. Для решения проблемы надо просто картинки подгрузить раньше на загрузке страницы, выглядит это так:&lt;br /&gt;
&lt;pre class=&quot;brush: javascript; gutter: false;&quot;&gt;var preloadImages = {};
preloadImages[&quot;image1&quot;] = &#39;Images/image1.png&#39;;
preloadImages[&quot;image2&quot;] = &#39;Images/image2.png&#39;;
...
preloadImages[&quot;image3&quot;] = &#39;Images/image3.png&#39;;
preloadImages[&quot;default&quot;] = &#39;Images/default.png&#39;;

function changeImage(key) {
    if (typeof key != &#39;undefined&#39;) {
        $(&#39;#image&#39;).attr(&#39;src&#39;, preloadImages[key]);
    }
    else {
        $(&#39;#image&#39;).attr(&#39;src&#39;, preloadImages[&quot;default&quot;]);
    }
};

(function loadImages() {
    for (key in preloadImages) {
    var img = new Image();
    img.src = preloadImages[key];
    }
})();
&lt;/pre&gt;&lt;br /&gt;
Затем можно использовать типо onmouseover=&quot;changeImage(&#39;image1&#39;);&quot; onmouseout=&quot;changeImage();&quot;.&lt;br /&gt;
По идее все должно работать, но картинки все равно мигают :/ Firebug показывает, что картинки подгружены. Но тогда я увидел следующее&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-JjudkE1WEm0AJUzgeJ5zXp15YMbP8m0PJxS07G-iPbG5PCT6iKCE3TaiNw70G8Kofn0MBk-71E4kBu1qHfwgp-ZKiEisoeYAuN-bq20BGZxUpfStOxAvDAhtnbMfSJuFL9x0eeR-34U/s1600/SS-2010-10-24_14.19.22.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-JjudkE1WEm0AJUzgeJ5zXp15YMbP8m0PJxS07G-iPbG5PCT6iKCE3TaiNw70G8Kofn0MBk-71E4kBu1qHfwgp-ZKiEisoeYAuN-bq20BGZxUpfStOxAvDAhtnbMfSJuFL9x0eeR-34U/s1600/SS-2010-10-24_14.19.22.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
В запросе идет хедер, что кэшировать не надо, а в ответе нифига. Картинка просто не кэшируется и каждый раз когда я меняю src она запрашивается заново. Осталось включить кэширование картинок и вроде бы должно заработать. Настройку кэширования статического контента в IIS6 можно посмотреть &lt;a href=&quot;http://www.codeproject.com/KB/aspnet/CachingImagesInASPNET.aspx&quot;&gt;здесь&lt;/a&gt;. Ниже показано как настроить тоже самое в IIS7.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8opPFWeqG2DB0v51Z9bfQpNdq23dGqNpYHPld4PoArbGhyGi9VRxhshkJBj5FpeNpJy5kLYjcHuRNiYsl0jx2ewLStOAlTe0AlWYz4SlkBCBMLd3-2C7cDl54GyF6rlFdPQ0R_WXyDKY/s1600/SS-2010-10-24_14.26.45.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8opPFWeqG2DB0v51Z9bfQpNdq23dGqNpYHPld4PoArbGhyGi9VRxhshkJBj5FpeNpJy5kLYjcHuRNiYsl0jx2ewLStOAlTe0AlWYz4SlkBCBMLd3-2C7cDl54GyF6rlFdPQ0R_WXyDKY/s1600/SS-2010-10-24_14.26.45.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Сначала выбираем папку с картинками (тоже самое можно сделать и для css папка), затем открываем &quot;Заголовки ответов HTTP&quot;.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT4cEDxEY6SzRT5MJNcuFI-6t1Vsn7LgP8OOvuCH6LeoVCyKb1rdAdvL69E6YhNGRgLAUd4gMGaAYFYkYVbY7sSwca4bB1Sw6W71RCt4Cd8xRsJ48BKME7zOUtTPOUQKAwEaDXUq6VQIc/s1600/SS-2010-10-24_14.29.34.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT4cEDxEY6SzRT5MJNcuFI-6t1Vsn7LgP8OOvuCH6LeoVCyKb1rdAdvL69E6YhNGRgLAUd4gMGaAYFYkYVbY7sSwca4bB1Sw6W71RCt4Cd8xRsJ48BKME7zOUtTPOUQKAwEaDXUq6VQIc/s1600/SS-2010-10-24_14.29.34.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Последовательность действий сверху вниз. После нажатия OK у вас будет 3 новых вещи:&lt;br /&gt;
1. В папке для которой мы настраивали кеш (Img) появится web.config (его надо включить в solution).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjHC_KIha5APNwx5vZI2OwdjNgprY0tcWA8yX6SQSEw3DO_SxdKFN9dseHx8TOOE5nqgxZIYFP_0vpK9K1kBPxItMc8nchB66OPxw_94M0d2vrmtBM2F7ChceJkU1SNgOc7wStn1Y2k-w/s1600/SS-2010-10-24_14.32.22.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjHC_KIha5APNwx5vZI2OwdjNgprY0tcWA8yX6SQSEw3DO_SxdKFN9dseHx8TOOE5nqgxZIYFP_0vpK9K1kBPxItMc8nchB66OPxw_94M0d2vrmtBM2F7ChceJkU1SNgOc7wStn1Y2k-w/s1600/SS-2010-10-24_14.32.22.png&quot; /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;2. В заголовке ответа появится хедер Cache-Control, говорящий о том, что картинка кешируется. Даже если следующий раз браузер захочет потянуть картинку, то в firebug вы увидите в ответ на GET запрос не 200 код, а 206. Значит картинка берется из кэша.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUwmMEyVcNdg2lm_syF7ennT7dTtHfHkTAjTk81tH99puwgS6VlV6unl4Z-YyZ1r_k-9cSQHSvnLhn6qyYl9LyrSzqMYy9ViNHdvXBXW1gWvRKTguqs9rEd9m2JhWW5zdqp1HK-XVmI_0/s1600/SS-2010-10-24_14.37.45.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUwmMEyVcNdg2lm_syF7ennT7dTtHfHkTAjTk81tH99puwgS6VlV6unl4Z-YyZ1r_k-9cSQHSvnLhn6qyYl9LyrSzqMYy9ViNHdvXBXW1gWvRKTguqs9rEd9m2JhWW5zdqp1HK-XVmI_0/s1600/SS-2010-10-24_14.37.45.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;3. Ну и 3 это результат, картинки не мигают.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/5180961933592340847/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2010/10/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/5180961933592340847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/5180961933592340847'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2010/10/blog-post.html' title='Как заставить браузер принудительно кэшировать картинки'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-JjudkE1WEm0AJUzgeJ5zXp15YMbP8m0PJxS07G-iPbG5PCT6iKCE3TaiNw70G8Kofn0MBk-71E4kBu1qHfwgp-ZKiEisoeYAuN-bq20BGZxUpfStOxAvDAhtnbMfSJuFL9x0eeR-34U/s72-c/SS-2010-10-24_14.19.22.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-7224315912368676843</id><published>2010-05-18T14:27:00.000+03:00</published><updated>2010-05-18T14:27:09.555+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>Как отформатировать сжатый JS файл</title><content type='html'>Иногда для отладки или для личных нужд вам нужно выровнять сжатый JS файл, который представлен в виде строки, без отступов, пробелов, переносов и тп. Это можно сделать &lt;a href=&quot;http://jsbeautifier.org/&quot;&gt;online&lt;/a&gt; - вставил, нажал, скопировал обратно (можно выставить размер отступов и тп). И там же есть ссылка на саму утилиту, она open source.</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/7224315912368676843/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2010/05/js.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/7224315912368676843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/7224315912368676843'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2010/05/js.html' title='Как отформатировать сжатый JS файл'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-1906774563573291715</id><published>2010-05-11T16:03:00.000+03:00</published><updated>2010-05-11T16:03:52.165+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><category scheme="http://www.blogger.com/atom/ns#" term="Debug"/><category scheme="http://www.blogger.com/atom/ns#" term="IIS"/><title type='text'>Как определить к какому пулу относиться w3wp процесс в IIS 7</title><content type='html'>Если у вас сайт развернут на IIS 7, для того чтоб его отдебажить, надо приэтачиться к процессу w3wp.exe. В одно время у вас может работать несколько сайтов и каждый может принадлежать к своему пулу. Когда вы этачитесь к процессу (рисунок ниже), то начинаем гадать, попал не попал, подсветились брейкпоинты или нет :))&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbZ30JnihGxb51c9LTlP8oU7zHca3Hyl7C16k5Ot-dViYTfaJs7LEq3rAn7_QY7SgTG5vGuAEbSgQHpP-sgsGKkaaPsWjq1fVEtuXlmTV0yQo6BPI-0YG0ds8ju3614NABg5lkvym-0Q/s1600/SS-2010-05-11_15.50.31.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;59&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbZ30JnihGxb51c9LTlP8oU7zHca3Hyl7C16k5Ot-dViYTfaJs7LEq3rAn7_QY7SgTG5vGuAEbSgQHpP-sgsGKkaaPsWjq1fVEtuXlmTV0yQo6BPI-0YG0ds8ju3614NABg5lkvym-0Q/s640/SS-2010-05-11_15.50.31.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Для того чтоб точно попасть, можно посмотреть, что к чему относится с помощью утилиты для администрирования IIS с командной строки - APPCMD, которая находится по пути &#39;%systemroot%\system32\inetsrv\&#39;. Детально можете разобраться по докам или &#39;/?&#39;. Нам нужно только  &#39;WP администрирование рабочих процессов&#39;. Пример использования и результат ниже. Мы видим ID процесса и пул к которому сайт в этом процессе относится.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiok2KoIMKsNHNcZVkOrtaTzA-Wrdq8s_g1YpCKIxdQfOxF__w_89HGoEUIq2HK_cPLP-djUpLfejoPubyicbCuOxY78figS76EA6SSjXGW18CIcm47l4qKdG2_-_DZ-02J7zgc7Wa3pCM/s1600/SS-2010-05-11_15.55.36.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;146&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiok2KoIMKsNHNcZVkOrtaTzA-Wrdq8s_g1YpCKIxdQfOxF__w_89HGoEUIq2HK_cPLP-djUpLfejoPubyicbCuOxY78figS76EA6SSjXGW18CIcm47l4qKdG2_-_DZ-02J7zgc7Wa3pCM/s640/SS-2010-05-11_15.55.36.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/1906774563573291715/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2010/05/w3wp-iis-7.html#comment-form' title='Комментарии: 4'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/1906774563573291715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/1906774563573291715'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2010/05/w3wp-iis-7.html' title='Как определить к какому пулу относиться w3wp процесс в IIS 7'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbZ30JnihGxb51c9LTlP8oU7zHca3Hyl7C16k5Ot-dViYTfaJs7LEq3rAn7_QY7SgTG5vGuAEbSgQHpP-sgsGKkaaPsWjq1fVEtuXlmTV0yQo6BPI-0YG0ds8ju3614NABg5lkvym-0Q/s72-c/SS-2010-05-11_15.50.31.png" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-913278598714127223</id><published>2010-05-07T01:55:00.005+03:00</published><updated>2010-05-07T02:08:32.108+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><category scheme="http://www.blogger.com/atom/ns#" term="Bulk Operations"/><category scheme="http://www.blogger.com/atom/ns#" term="Usability"/><title type='text'>Индикация прогресса при длительных операциях в ASP.NET</title><content type='html'>Я думаю вы сталкивались с ситуацией, когда нужно что-то импортить, например CSV файл с продуктами, кастомерами, синхронизировать базы или работать с каким то тормознутым веб сервисом. Во всех перечисленных и подобных случаях страница &quot;лочится&quot; пока не закончится операция, но нам хотелось бы видеть какой-то прогресс, о чем сегодня и поговорим.&lt;br /&gt;
Недавно мне нужно было импортить продукты из индусского сервиса, не важно как, главное что страница лочилась на 1-2 минуты и непонятно, что там происходило и когда оно завершалось.&lt;br /&gt;
Существует несколько решений как можно узнать прогресс на длительной операции:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Сохранять прогресс в сессию, а на клиенте должен быть таймер, который после запуска длительной операции будет опрашивать страницу с какой-то периодичностью, например каждую секунду или тп. Этот метод описан &lt;a href=&quot;http://devarchive.net/displaying_progress_bar_for_long_running_processes.aspx&quot;&gt;здесь&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Создать вспомогательную страницу в iframe, при запуске которой в OnLoad сразу начинается длительная операция. Во время прогресса надо писать в Response вызов JS функции, которая будет вызываться в родительском окне, с которого был запущен iframe. Этот метод описан &lt;a href=&quot;http://encosia.com/2007/10/03/easy-incremental-status-updates-for-long-requests/&quot;&gt;здесь&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Сделать страницу асинхронной, через Async или &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.web.ui.icallbackeventhandler.aspx&quot;&gt;ICallbackEventHandler Interface&lt;/a&gt; и опять-таки через таймер опрашивать сервер. Это способ можно отнести как вариация второго.&lt;/li&gt;
&lt;/ol&gt;Из всех перечисленных мне не нравится никакой :)&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Потому, что надо делать вспомогательную страницу. Хоть автор и советует использовать только этот метод, но мне он кажется недоделаным.&lt;/li&gt;
&lt;li&gt; Потому, что както-то по индусски... опрашивать постоянно сервер? может в каком-то случае это и будет лучший вариант, но не сегодня.&lt;/li&gt;
&lt;li&gt;Ограниченные возможности по передаче параметров от клиента к серверу и наоборот. Можно передать, что угодно, но только в одной строке. А дальше думать формат, парсить... ну и + оргументы выше в пункте 2.&lt;/li&gt;
&lt;/ol&gt;Мое решение похожее больше на 1 вариант, но без iframe. В результате  получим примерно следующее:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizXXaOgrfhvQzKiKIhO3tYLpDeEro74HeS0gU_ulJEIty5RLKAozrKgKuxCvZFIRR7cb7i7aMaSLIoawJKiMgeCj5KP6E0HRDJ3gi2jypl6k205de74RyJFc0yFx-4LZyW031AHCBPwOU/s1600/SS-2010-05-07_01.09.18.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;105&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizXXaOgrfhvQzKiKIhO3tYLpDeEro74HeS0gU_ulJEIty5RLKAozrKgKuxCvZFIRR7cb7i7aMaSLIoawJKiMgeCj5KP6E0HRDJ3gi2jypl6k205de74RyJFc0yFx-4LZyW031AHCBPwOU/s400/SS-2010-05-07_01.09.18.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyLwjRZpa-sPjRfu_vp9y1q9_8pfpBca5DiWJCLzh2TIV01q4Vo4kEwjrVrdkTfLhAjFur7NocYva97WjvGTQrEMcbdugWRllAb99cY2FV4sZ4_YiN-Zso954abmpXwszslHFF4qcarNE/s1600/SS-2010-05-07_01.11.39.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;111&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyLwjRZpa-sPjRfu_vp9y1q9_8pfpBca5DiWJCLzh2TIV01q4Vo4kEwjrVrdkTfLhAjFur7NocYva97WjvGTQrEMcbdugWRllAb99cY2FV4sZ4_YiN-Zso954abmpXwszslHFF4qcarNE/s400/SS-2010-05-07_01.11.39.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;На картинках выше показана индикация прогресса во время импорта продуктов, категорий и брендов из сервиса. Initialization показывает прогресс когда выполняется аутентификация или может создание вспомогательный  классов, по вашему желанию. В мое случае я логинился на сервис. А теперь как это делалось. Для этого нам понадобится &lt;b&gt;одна&lt;/b&gt;! страница, класс с длительной операцией, интерфейс через который будет уведомляться страница о прогрессе, пару js функций которые будут двигать прогресс бар и немного css для прогресс бара.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; gutter: true;&quot;&gt;public interface IProgressReporter
    {
        void ReportInitializationFinished();
        void ReportCategoriesProgress(int count, int completed);
        void ReportProductsProgress(int count, int completed);
        void ReportBrandsProgress(int count, int completed);
        void ReportException(Exception exception);
    }
&lt;/pre&gt;&lt;br /&gt;
Методы интерфейса как я и говорил мы будет дергать из класса, который занимает длительным процессом. Ниже приведен сам класс, он примитивный, просто чтоб показать саму суть.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; gutter: true;&quot;&gt;public class LongOpperations
    {
        public void ProcessCatalog(IProgressReporter progressReporter)
        {
            // some initialization, web service authentication, whatever
            Thread.Sleep(5000);
            progressReporter.ReportInitializationFinished();

            for (int i = 0; i &amp;lt; 100; i++)
            {
                Thread.Sleep(100);
                progressReporter.ReportCategoriesProgress(100, i + 1);
            }

            for (int i = 0; i &amp;lt; 20; i++)
            {
                Thread.Sleep(200);
                progressReporter.ReportBrandsProgress(20, i + 1);
            }

            for (int i = 0; i &amp;lt; 100; i++)
            {
                Thread.Sleep(200);
                progressReporter.ReportProductsProgress(100, i + 1);
            }
        }
    }
&lt;/pre&gt;Отчетом о прогрессе выступает наша страница, для этого нужно реализовать наш интерфейс. Потом, когда вы будем стартовать длительную процедуру, мы передадим себя, страницу, в наш обработчик. В итоге получаем подобие шаблона Visitor. Самое интересное находится в методе Render. Начало ясное, если мы не нажали кнопку, то просто рендерим страницу как есть. Дальше мы должны отключить буферизацию страницы, в другом случае IE например закеширует первые 256 байт ответа и мы получим не то, что ожидали. Поэтому отключаем. Если мы после этого начнем репортить прогресс, то мы перетрем то, что существует на странице, поэтому ренедрим её как есть, а потом будет дописывать в Response наши ответы. Основная идея заключается в том, чтоб в Response записать вызов клиентской функции и сразу вывести его на страницу через Flush. Как только на странице появится script, он сразу выполнится, тем самым подвинет прогресс бары.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp; gutter: true;&quot;&gt;public partial class _Default : Page, IProgressReporter
    {
        private bool started;
        protected override void Render(HtmlTextWriter writer)
        {
            if (!started)
            {
                base.Render(writer);
                return;
            }

            Response.BufferOutput = false;
            base.Render(writer);
            Response.Flush();

            ReportInitializationStarted();
            new LongOpperations().ProcessCatalog(this);
        }

        protected void OnStartClick(object sender, EventArgs e)
        {
            started = true;
        }

        public void ReportInitializationStarted()
        {
            Response.Write(&quot;&amp;lt;script&amp;gt;ReportInitializationStarted();&amp;lt;/script&amp;gt;&quot;);
            Response.Flush();
        }

        public void ReportInitializationFinished()
        {
            Response.Write(&quot;&amp;lt;script&amp;gt;ReportInitializationFinished();&amp;lt;/script&amp;gt;&quot;);
            Response.Flush();
        }

        public void ReportCategoriesProgress(int count, int completed)
        {
            ReportProgress(pnlCategoryProgress.ClientID, lblCategory.ClientID, count, completed);
        }

        public void ReportProductsProgress(int count, int completed)
        {
            ReportProgress(pnlProductProgress.ClientID, lblProduct.ClientID, count, completed);
        }

        public void ReportBrandsProgress(int count, int completed)
        {
            ReportProgress(pnlBrandProgress.ClientID, lblBrand.ClientID, count, completed);
        }

        public void ReportException(Exception exception)
        {
            string progressCall = string.Format(&quot;&amp;lt;script&amp;gt;ReportException(&#39;{0}&#39;,&#39;{1}&#39;);&amp;lt;/script&amp;gt;&quot;, exception.Message, exception.StackTrace);

            Response.Write(progressCall);
            Response.Flush();
        }

        private void ReportProgress(string progressBar, string percentLabel, int count, int completed)
        {
            double progress = (count == 0) ? 100 : (100.0 / count) * completed;

            string progressCall = string.Format(&quot;&amp;lt;script&amp;gt;UpdateProgress(&#39;{0}&#39;,&#39;{1}&#39;,{2},{3},{4});&amp;lt;/script&amp;gt;&quot;, progressBar, percentLabel, progress, count, completed);

            Response.Write(progressCall);
            Response.Flush();
        }
&lt;/pre&gt;&lt;br /&gt;
Клиентский функции, которые двигают прогресс бары и тп.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: javascript; gutter: true;&quot;&gt;function UpdateProgress(progressBarId, percentLabelId, progress, count, completed) {
            var progressBar = document.getElementById(progressBarId);
            var progressLabel = document.getElementById(percentLabelId);
            
            progressLabel.innerHTML = (progress == -1) ? &#39;0&#39; : completed + &#39;/&#39; + count;
            progressBar.style.width = progress + &#39;%&#39;;            
        };

        function ReportException(message, stack) {
            var p = document.createElement(&#39;p&#39;);
            p.innerHTML = &#39;Message: &#39; + message + &#39;
 Stack: &#39; + stack;
            document.getElementById(&#39;error&#39;).appendChild(p);
        };

        function ReportInitializationFinished() {
            var pnl = document.getElementById(&#39;pnlInitializing&#39;);
            pnl.className = null;
        };

        function ReportInitializationStarted() {
            var pnl = document.getElementById(&#39;pnlInitializing&#39;);
            pnl.className = &#39;progress&#39;;
            pnl.style.width = &#39;100%&#39;            
        };
&lt;/pre&gt;&lt;br /&gt;
Вот еще кусок разметки для ясности. Весь приводить не буду, т.к. там тоже самое и немного css.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibOevlijOIS6tf6GKGsB99EpZma2bukCg1HGvbotGKQDLsDbWOj11G1P74m7RujIAwmbW-7LutWj2SN8oTXYvWdmZ6abDC2_78M3rGF8WIjWLyI17lzXjqCcLAUhmZHm0kZc8H02rwLEQ/s1600/SS-2010-05-07_01.47.56.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;252&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibOevlijOIS6tf6GKGsB99EpZma2bukCg1HGvbotGKQDLsDbWOj11G1P74m7RujIAwmbW-7LutWj2SN8oTXYvWdmZ6abDC2_78M3rGF8WIjWLyI17lzXjqCcLAUhmZHm0kZc8H02rwLEQ/s640/SS-2010-05-07_01.47.56.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
Вот и все. Основная идея в том, чтоб запустив длительный процесс сразу отдавать ответ в виде js сриптовой инъекции, которая будет обновлять прогресс. Вы можете наделать любых методов в интерфейсе. Они могут быть настолько детальными на сколько вам необходимо. В моем случае я хотел еще справа от прогресс баров добавить лог ошибок и добавил соответсвующий метод в инерфейсе ReportException, оставил для примера.&lt;br /&gt;
Буду рад услышать ваши идеи и отзывы.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/913278598714127223/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2010/05/aspnet.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/913278598714127223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/913278598714127223'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2010/05/aspnet.html' title='Индикация прогресса при длительных операциях в ASP.NET'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizXXaOgrfhvQzKiKIhO3tYLpDeEro74HeS0gU_ulJEIty5RLKAozrKgKuxCvZFIRR7cb7i7aMaSLIoawJKiMgeCj5KP6E0HRDJ3gi2jypl6k205de74RyJFc0yFx-4LZyW031AHCBPwOU/s72-c/SS-2010-05-07_01.09.18.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-1317893882623800116</id><published>2010-03-22T17:58:00.001+02:00</published><updated>2010-03-22T17:59:11.621+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><title type='text'>Способ перевести сайт в maintenance mode</title><content type='html'>Вопрос очень простой, но в основном те решения, которые я встречал сводились к созданию второго сайта. Один был рабочий, а когда его надо было обновить включали второй сайт, а первый тушили. Еще был вариант с модулем, который по ключу в конфиге включался или выключался и показывал соответствующую страницу maintenance mode.&lt;br /&gt;
&lt;br /&gt;
В asp.net 2.0 появился способ сделать это удобно и красивей. Вам нужно просто создать файл с названием app_offline.htm (именно так, по другому работать не будет) и положить его в корень своего сайта, после этого asp.net будет обрубать все &lt;u&gt;новые запросы&lt;/u&gt;, а старые нормально отработаю до очередного нового.&lt;br /&gt;
&lt;br /&gt;
Когда вы закончите обновлять сайт, просто переименуйте файл или удалите его и все заработает.&lt;br /&gt;
По умолчанию, если размер app_offline файла меньше 512 кб, то IE будет показывать friendly error page. &lt;br /&gt;
&lt;br /&gt;
Очень удобно, удачи.</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/1317893882623800116/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2010/03/maintenance-mode.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/1317893882623800116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/1317893882623800116'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2010/03/maintenance-mode.html' title='Способ перевести сайт в maintenance mode'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-329418352356606474.post-4371623997508628557</id><published>2010-03-15T16:21:00.000+02:00</published><updated>2010-03-15T16:21:56.581+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="хобби"/><title type='text'>Доделал Tomcat F14-A</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi31nN2kcqBJu_xwrLHKL3GIEfbjzWPVYUuzfJCpQReZO-EV5hnsf_Eot6rFPbvp5Rm0Gd0JRE-C0gNBEGVH5RU-jiIr8ga-41UXurvj3Kxa_i1S2-UwriGNcXy8dGZ5yB425C9VY4Wm8c/s1600-h/Tomcat+F14-A.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;356&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi31nN2kcqBJu_xwrLHKL3GIEfbjzWPVYUuzfJCpQReZO-EV5hnsf_Eot6rFPbvp5Rm0Gd0JRE-C0gNBEGVH5RU-jiIr8ga-41UXurvj3Kxa_i1S2-UwriGNcXy8dGZ5yB425C9VY4Wm8c/s640/Tomcat+F14-A.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
На днях закончил очередную модель Tomcat F14-A (modelist). Сама модель достаточно хорошо исполнена, глубокие прорези, подгонять детали напильником особо не пришлось. Также хочется отметить качество декалей, не рвутся, накладываются легко. Единственная проблема, это то, что декали которые шли в комплекте не понятно к какой эскадрильи относятся, обычно на килях черепа или пегасы (каталог dragon 2008). &lt;br /&gt;
В общем я доволен, даже меняется стреловидность крыла, прикольно :)</content><link rel='replies' type='application/atom+xml' href='http://delmadman.blogspot.com/feeds/4371623997508628557/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://delmadman.blogspot.com/2010/03/tomcat-f14.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4371623997508628557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/329418352356606474/posts/default/4371623997508628557'/><link rel='alternate' type='text/html' href='http://delmadman.blogspot.com/2010/03/tomcat-f14.html' title='Доделал Tomcat F14-A'/><author><name>Madman</name><uri>http://www.blogger.com/profile/13588895718633545729</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='21' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnPkTfkrbe96NqMmkDVJFFVz79Sz_0f8z5wk5i2q5hcm8hYpg5MtqzCeW84U1l5ZfqHgyJXvK5VLVdgqx10MzVBqVpyU5-kSx7kP4pBTcEGpOugrSRNOtEDkNzf0Cgkg/s1600/*'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi31nN2kcqBJu_xwrLHKL3GIEfbjzWPVYUuzfJCpQReZO-EV5hnsf_Eot6rFPbvp5Rm0Gd0JRE-C0gNBEGVH5RU-jiIr8ga-41UXurvj3Kxa_i1S2-UwriGNcXy8dGZ5yB425C9VY4Wm8c/s72-c/Tomcat+F14-A.jpg" height="72" width="72"/><thr:total>0</thr:total></entry></feed>