понедельник, 15 декабря 2014 г.

О передаче параметров в C#

Давайте сразу начнем с кода. У нас есть вот такой код, давайте разберемся почему он выводит то, что выводит:

 
    class Program
    {
        static void Main(string[] args)
        {
            int a = 1;
            ProcessValue(a);
            Console.WriteLine(a.ToString());
            //здесь будет выведено 1

            TestClass test = new TestClass();
            test.val = 2;
            ProcessRef(test);
            Console.WriteLine(test.val.ToString());
            //здесь будет выведено 10

            TestClass test = new TestClass();
            test.val = 3;
            Process(test);
            Console.WriteLine(test.val.ToString());
            //а здесь будет выведено 3
        }

        static void ProcessValue(int par)
        {
            par = 3;
        }

        static void ProcessRef(TestClass par)
        {
            par.val = 10;
        }

        static void Process(TestClass par)
        {
            par = new TestClass();
            par.val = 100;
        }
    }
 

    public class TestClass
    {
        public int val;
    }


Вы, наверняка, знаете, что в .Net есть значимые (value) и ссылочные (reference) типы. Первые - размещаются полностью в стеке, а вторые размещаются в управляемой куче, а в стеке размещается только указатель на них.


воскресенье, 7 декабря 2014 г.

Обработка исключений при работе с WCF-сервисами

Наверняка вы сталкивались с ситуацией, когда в случае ошибки в WCF-сервисе нужно передать клиенту какие-либо данные либо, например, подробное описание что случилось. Очень часто встречаются реализации WCF- сервисов, использующие возвращаемые клиенту объекты с дополнительными, используемыми только в случае ошибки, полями, даже если реализация метода не требует возврата какого-либо результата клиенту. Так делают потому, что если просто выбросить исключение, то клиент не получит практически никакой информации о том, что случилось. Представьте, что у нас есть WCF сервис вот с таким простым контрактом и реализацией.


  
    //контракт
    [ServiceContract]
    public interface IDataService
    {        
        [OperationContract]        
        void TestError();
    }

    //реализация
    public void TestError()
    {
       throw new Exception("Error!");
    }


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

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


суббота, 6 декабря 2014 г.

Несколько мыслей о получении IP адреса клиента в ASP.NET

Получение IP-адреса клиента - это, наверное, один из самых интересных и неоднозначных вопросов не только в ASP.NET, но и вообще в веб-разработке. Вариантов, как это сделать несколько, и у каждого из способов есть как сторонники, так и противники. Попробую рассказать вам об этих вариантах, чем они отличаются друг от друга и что лучше использовать.

Итак, самый широко известный в мире ASP.NET способ получения IP-адреса клиента - это использование HttpContext.Current.Request.UserHostAddress, который, по сути является оберткой над HTTP заголовком REMOTE_ADDR, в которую записывается адрес хоста от которого серверу пришел запрос. А этот заголовок используется практически во всех языках программирования, для целей определения IP клиента. И везде не утихают споры правильно ли использовать именно его. Почему? Потому, что REMOTE_ADDR содержит адрес компьютера, установившего соединение с сервером. Во времена становления интернет и появления протокола HTTP этик компьютером почти наверняка являлся клиент, так что все было хорошо. Сейчас же, в большинстве случаев, в REMOTE_ADDR будет адрес прокси сервера внутренней сети (корпоративной, или домашней - смысла это не меняет) через который прошел запрос клиента.
И еще один пример, с которым, особенно часто сталкиваются Linux программисты, в результате криво настроенного nginx. ;)
Представьте себе ситуацию, что у вас есть криво настроенный балансировщик нагрузки. В таком случае в REMOTE_ADDR будет 10.10.0.2, что, естественно совершенно не клиентский адрес.



четверг, 27 ноября 2014 г.

Как получить IP-адрес клиента в WCF-сервисе.

Если вам нужно узнать с какого адреса приходит обращение к вашему WCF-сервису, то сделать это вы можете несколькими способами в зависимости от версии .Net Framework. Давайте по порядку.
В версии 3.0 (то есть, самая первая версия .Net, в которой стала доступна WCF) по заверениям Microsoft не существует гарантированного способа это сделать.  В принципе, если сервис хостится на IIS, то можно попробовать пару извращений, типа получения IP-адреса клиента из логов сервера (хотя встает вопрос как определять какая из записей лога соответствует текущему запросу). В общем, предлагаю придерживаться позиции Microsoft по этому вопросу ;)
В версии .Net 3.5 в WCF появляется класс  System.ServiceModel.OperationContext, так что подключаем сборку  System.ServiceModel и используем вот такой код, который и вернет на IP клиента:


воскресенье, 23 ноября 2014 г.

Отладка 64-битных веб-приложений в Visual Studio

Представьте себе ситуацию, то вы разрабатываете веб-приложение, которое либо просто само по себе 64-битное (x64), либо еще и использует какие-либо x64 библиотеки. При попытке запуска отладки такого приложения вы получите сообщение об ошибке из серии BadImageFormatException.


А происходит такое по тому, что IIS Express, используемый в Visual Studio для отладки, работает как 32-битный процесс, в чем легко убедится, взглянув в Task Manager:

И если при использовании версии Vsual Studio до 2012 единственным способом было использование для отладки локального "большого" IIS, соответствующим образом настроив свойства проекта:


суббота, 22 ноября 2014 г.

Ошибки 0x800F081F и 0x800F0906 при установке .Net Framework 3.5 на Windows 8/8.1

По умолчанию .Net Framework 3.5 в Windows 8 и 8.1 не устанавливается, так что, во-первых, он не будет доступен в Visual Studio, а во-вторых, при попытке запустить что-то, что использует .Net 3.5 (например Windows 7 SDK) вы увидите примерно такое предложение:


Не проблема, наверняка подумаете вы, и нажмете "Установить".  В большинстве случае это, к сожалению, ни к чему хорошему не приведет и вы получите ошибку

В английском варианте Windows ошибка звучит так:
0x800F0906  The source files could not be downloaded.
Windows couldn't connect to the Internet to download necessary files. Make sure that you're connected to the Internet and click "Retry" to try again.


суббота, 15 ноября 2014 г.

Помещение текущей даты в переменную в .bat-файле.

Недавно столкнулся с задачей, требующей ежедневного архивирования содержимого папки в архив вида "название файлаDD_MM_YYYY". Чтобы это сделать в одном батнике надо выполнить несколько действий:


1. Понять как выводится дата в вашей локали. Для этого запускаем CMD и пишем DATE/T. Русская локаль -самая простая, в ней текущая дата выводится в виде 15.11.2014. В Английской, например, все несколько сложнее, там перед датой идет сокращенное название дня недели, например Sat 15.11.2014. На на данном этапе интересует та часть строки, которая содержит дату. Чтобы получить ее, на нужна сделать так:

for /f %%i in ('DATE/T') do set date=%%i 

или, если перед датой что-то находится, например Sat

for /f "tokens=2" %%i in ('DATE/T') do set date=%%i

2. Теперь нам нужно заменить точки или слеши в дате на подчеркивание.


четверг, 13 ноября 2014 г.

Microsoft открыла исходные коды .Net Core

Сегодня Microsoft открыла исходный код основных компонент ядра .Net. Все исходника выложены на GitHub под лицензией MIT, так что, теперь можете изучать исходники .Net без дополнительных телодвижений типа Relector, и использовать части кода в своих продуктах.

Пока доступен код только нескольких компонент:
  • ASP.NET 5
  • EntityFramework
  • .NET Core 5
  • .NET Compiler Platform ("Roslyn")
Но, Microsoft обещает скоро выложить еще.

Лежит все тут: https://github.com/Microsoft/dotnet


четверг, 6 ноября 2014 г.

Что такое EntityValidationErrors и как с ним бороться.

При использовании Entity Framework вы можете столкнуться с ошибкой, гласящей "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details." Причина появления этой ошибки в большинстве случаев - банальна, либо вы забыли какие ограничения существуют на полях в вашей базе данных, либо, если БД в вашей компании занимается отдельный человек, то он вам забыл о чем-то сообщить. ;)


EntityValidationErrors - это коллекция объектов DbEntityValidationResult, каждый из которых содержит информацию об ошибках одной EF-сущности в виде объектов DbValidationError.
На самом деле, ничего страшного в этой ошибке нет, и можно легко узнать в чем конкретно у нас ошибка в коде. Все, что для этого необходимо - это обернуться вызов метода SaveChanges() вот в такой блок try-catch:


среда, 5 ноября 2014 г.

ASP.NET 4.5 и Unobtrusive Validation, Progressive Degradation и что это все нам дает.

В ASP.NET 4.5 среди прочих нововведений, во всю начал применяться так называемый подход Unobtrusive JavaScript, то есть, "ненавязчивый JavaScript" и использование jQuery. Эта технология уже применяется в ASP.NET MVC, по-моему, с третьей версии, и вот, теперь дело дошло и до WebForms.


Что же это за зверь "Unobtrusive JavaScript"? Это относительно новый подход к разработке клиентской части web-страниц, предполагающий несколько вещей:

  1. Отделение поведения (JavaScript) от структуры и представления (HTML/CSS). То есть, такой своеобразный вариант клиентского MVC.
  2. Попытки избежать традиционных проблем JavaScript (т.е., максимально возвожная браузеро- и платформонезависимость и масштабируемость)
  3. Использование подхода Graceful degradation, то есть приложение должно оставаться работоспособным при использовании даже старых браузеров возможно вообще не поддерживающих JavaScript.
В ASP.NET все эти принципы проявляются в виде Unobtrusive Validation, о которой я постараюсь вам рассказать применительно к общей концепции Unobtrusive JavaScript.

В качестве примера давайте создадим простой web-приложение на ASP.NET 4.5 и добавим в него одну единственную страничку с текстовым полем, кнопкой и валидатором того, что текстовое поле заполнено. 

Как вы, наверное, помните, в предыдущих версиях добавление валидатора влекло за собой добавление в код страницы целой простыни JavaScript кода. А что сейчас? Давайте попробуем запустить наш пример.