Пишем код

Заметки о .net разработке

Archive for the ‘javascript’ Category

OpenApiGenerator: fixing multiple file upload for JS clients

without comments

Remember, I love swagger! And since we have it anyway, it’s kinda dumb to write requests to that API manually.
Why would anyone want to come up with something like axios.get(‘/user/123/payments?fromDate=2018-01-01’) without intellisense, type-checking and compile-time verifications? What if someday you change that API’s route?

OpenApiGenerator is a great solution to this. You could easily get typed-clients for your API in almost any language, and make requests as easy as UserApi.get(123, dateFrom).
But that’s a well-known thing, let’s get to the point of this article :)
OpenApiGenerator plays well with almost anything, but file arrays. File arrays were introduced to OpenApi recently, so not all the tools support them yet.
So, let’s say you have a backend method that accepts an array of files (files will be passed with the same name):

<br />
[HttpPost()]<br />
public IActionResult UploadFiles(IFormFile[] files)<br />

OpenApiGenerator will provide you with a proper JS method, but it won’t work and will generate something like:
<br />
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryIk1aWkovTmf7LSJX</p>
<p>------WebKitFormBoundaryIk1aWkovTmf7LSJX<br />
Content-Disposition: form-data; name="files"</p>
<p>[object File],[object File]<br />
------WebKitFormBoundaryIk1aWkovTmf7LSJX--<br />

Of course, that isn’t what we want. However, it’s quite easy to monkey-patch the generated ApiClient to achieve what we want. I know monkey-patching is dirty and you should probably fix this with inheritance&overriding, but I’ll leave this to you :) So, here’s the patch:
<br />
//this is to make ApiClient correctly handle array of files<br />
const oldBuildCollectionParam = ApiClient.instance.buildCollectionParam;<br />
ApiClient.instance.buildCollectionParam = function(param, collectionFormat) {<br />
    if (param == null) {<br />
        return null;<br />
    }<br />
    if (param.length > 0) {<br />
        if (param[0] instanceof File) {<br />
            return param;<br />
        }<br />
    }<br />
    return oldBuildCollectionParam.call(this, param, collectionFormat);<br />
};<br />

Written by Shaddix

Сентябрь 5th, 2018 at 11:58 дп

Posted in javascript

Доклад о веб-компонентах и Polymer

without comments

Сегодня отметился докладом на томском локальном митапе фронтэнд разработчиков TomskJS.
Рассказывал про веб-компоненты и Polymer. Презентацию смотреть на Слайдшаре

Веб-компоненты в веб-разработке на примере Polymer from ArturDr

или скачивать по ссылке.

Видео:

Written by Shaddix

Сентябрь 3rd, 2016 at 10:51 пп

Posted in javascript,web

Polymer и NotifyPropertyChanged в JavaScript

3 комментария

Есть замечательный фреймворк построения веб-приложений — Polymer. Это даже скорее не фреймворк, а реализация идеологии WebComponents в современных реалиях веб-браузеров.

Если кратко, то с его помощью можно реализовывать полноценный, удобный и быстрый (как с точки зрения производительности решения, так и скорости разработки) MVVM в JavaScript:

<br />
<dom -module id="my-component"><br />
  <template></p>
<h4>ToDo list for {{name}}:</h4>
<ul>
      <template is="dom-repeat" items="{{model.todoitems}}"></p>
<li>{{item.title}}</li>
<p>      </template>
    </ul>
<p>    <button title="ChangeName" on-tap="ChangeName"></button><br />
  </template><br />
</dom><br />
<script>
Polymer({
  is: 'my-component',
  name: 'Artur',
  model: {
    items: [
      {title: '1'}
    ]
  },
  ChangeName: function() {
    this.model.name = this.name + "_1";
  },
});
</script><br />

В WPF мы привыкли, что интерфейс перерисовывается автоматически, при изменении значения свойства: this.name = ‘New Name’;. Однако у многих js-mvvm-фреймворков, присвоения приходится производить с помощью магических функций: this.set(‘name’, this.name + «_1»). В Polymer успешно работает первый (удобный :)) вариант, однако при работе с массивами и вложенными объектами эти прелести заканчиваются. Код добавления новых элементов в список ToDo выглядит примерно так:
<br />
Add: function() {<br />
  this.push('items', {title: 'another item'});<br />
}<br />

Редактирование же элементов в списке (например, изменение title) будет еще более ужасным:
<br />
  this.set('items.1.title', 'new title!');<br />

Read the rest of this entry »

Written by Shaddix

Июль 4th, 2016 at 7:14 дп

Posted in javascript,web

Только React.js, только хардкор (aka долой Angular и Knockout)!

9 комментариев

Последние годы только ленивый не писал о javascript-фреймворках. AngularJS/KnockoutJS/Backbone/Ember — выбирай на вкус :) Но, озадачившись выбором фреймворка для небольшого веб-приложения с год назад, оказалось, что серебряной пули в мире js все еще не придумали.
Backbone и Ember слишком низкоуровневы и многословны, Knockout расстраивает постоянными конвертациями данных в observable, AngularJS.. да, почему бы не попробовать Angular, подумал я тогда. Энгуляр обладал приятным синтаксисом, структура Контроллеров была более менее близка и понятна и всё шло хорошо, пока.. пока мы не уперлись в довольно стандартную для Angular проблему произодительности.
Read the rest of this entry »

Written by Shaddix

Январь 29th, 2014 at 11:16 пп

Posted in agile,javascript,web

T4MvcJs — строготипизированный яваскрипт-хелпер для URL

6 комментариев

Не так давно я уже писал о решении проблемы «магических строк» в яваскрипте, примером таких строк могут служить url экшенов («/Home/Index?name=John&lastname=Doe»)

В разор-вьюшках проблему написания урлов «напрямую» можно решить с помощью T4Mvc: @Url.Action(MVC.Actions.Home.Index(«John», «Doe)). Проблема в том, что этот код — серверный, и написать что-то подобное в script.js — не получится.
В предыдущем посте я уже предлагал решение проблемы, однако(об этом я также писал) в нём была существенная недоработка. Новая версия T4MvcJs эти недоработки устраняет, и в результате мы, как и прежде, спокойно сможем писать в яваскрипт файлах что-то вроде: MvcActions.Home.Index(«John», «Doe»), и это будет полностью клиентский код.
Read the rest of this entry »

Written by Shaddix

Январь 18th, 2012 at 9:32 пп

Валидация JavaScript в ASP.Net MVC проекте — еще один велосипед или jsvalidator.codeplex.com

without comments

В предыдущей заметке я рассматривал существующие решения «псевдо-компиляции» яваскрипта и интеграции этих решений в asp.net проекты.

В итоге не найдя ничего идеального и решив, что собственный велосипед здесь не помешает, я и написал утилиту под названием jsvalidator. Найти её можно на codeplex, там же есть и краткое описание установки и конфигурирования. Данная заметка, по сути, будет переводом «официальной документации» собственного же сочинения :)

Если коротко, то jsvalidator это build-step с json-like конфигурационным файлом, проверяющая яваскрипт с помощью java-библиотеки google closure. Из этого следует и первое требование — для работы утилиты необходима установленная на компьютере java (с java.exe добавленным в системные пути (system PATH)).

После интеграции утилиты на каждый билд в вашей Visual Studio будет нечто вроде:

(в данном случае утилита сообщает нам о необъявленной переменной asd, по двойному клику на ошибке откроется js-файл на строчке с ошибкой, как мы и привыкли).
Read the rest of this entry »

Written by Shaddix

Январь 10th, 2012 at 3:01 пп

Unobtrusive validation и загрузка форм через аякс (full ajax website)

6 комментариев

При использовании «ненавязчивой» (unobtrusive) валидации форм в MVC проекте можно заметить, что если валидируемая форма была подгружена асинхронно, то валидация не сработает.

Поэтому после обновления частей страницы, содержащих формы, надо не забывать выполнить что-нибудь подобное:

<br />
$.validator.unobtrusive.parse($("#loadedContent"));<br />

(где #loadedContent — это айдишник подгруженной области).
В простейшем случае можно даже добавить этот код в обработчик события ajaxSuccess, чтобы уж точно не забыть :)
<br />
$.ajaxSuccess(function(e) { $.validator.unobtrusive.parse(document); });<br />

P.S. Заметить факт неработоспособности клиентской валидации может с легкостью помешать принцип graceful degradation — по-умолчанию валидация отработает нормально, но это будет серверная валидация :) При тестировании на localhost это и правда можно не заметить.

Традиционный пример проекта с этой небольшой функцией.

Written by Shaddix

Январь 8th, 2012 at 5:57 пп

Валидация JavaScript в ASP.Net MVC проекте — анализ существующих решений

3 комментария

Когда яваскрипт в веб-проекте занимает достаточно большую долю, и клиентские скрипты вырастают за рамки «инлайн-скриптов» с одной-двумя строчками вызова jquery-плагинов, вопрос о проверке и валидности яваскрипта встает достаточно явно (даже для .net-разработчиков, достаточно далеких от js в принципе :)).

Для меня эта проблема стала наиболее актуальной, когда я начал генерировать яваскрипт-хэлперы с помощью T4-шаблонов, и стало просто необходимым своевременно узнавать о том, что яваскрипт-переменная Constants.MainController.ContentId больше не существует (а была переименована в ContentsId). Также хотелось сократить цикл обнаружения банальных опечаток в названиях переменных — раньше об этом говорила консоль ошибок браузера, а хотелось видеть это на этапе билда.

В решении данной проблемы мне помогли «псевдо-компиляторы» яваскрипта, хотя, пожалуй, корректнее было бы называть их верификаторами синтаксиса.
Read the rest of this entry »

Written by Shaddix

Декабрь 26th, 2011 at 3:13 пп

Устранение magic-strings в javascript

without comments

Недавно я озадачился проблемой «магических строк», которые регулярно появляются в яваскрипте.

Допустим, у нас на страничке динамически генерируются блоки вида:

<br />
<span animate_period="10" animate_amplitude="20"></span><br />

И есть javascript-код, который ищет блоки с этими атрибутами и в соответствии со значениями применяет определенную анимацию. В итоге имена атрибутов (magic-strings по сути) дублируются во вьюшках/контроллерах и js-файлах.
Еще одной похожей проблемой становится посылка аякс-запросов к контроллерам:
<br />
$('#mydiv').load("http://mysite.ru/Items/GetItemInfo?id=20");<br />

URL запроса явно грозит нам опечатками и/или ошибками, когда этот адрес изменится.
Если мы пишем яваскрипт-код прямо в html файлах (а не в отдельных подключаемых скрипт-файлах), то можно, конечно, воспользоваться T4MVC и написать что-то вроде:
<br />
$('#mydiv').load("@Url.Action(MVC.Items.GetItemInfo())");<br />

Как раз о таком способе решения проблемы я недавно и писал. Но если js вы всё-таки выносите в отдельные файлы (а делать это надо — для уменьшения дублирования и клиентского кэширования), то проблема так просто не решается.

Столкнувшись с проблемой на довольно-таки большом проекте, в голову пришла мысль воспользоваться всей мощью шаблонов T4 и сгенерировать соответствующие javascript-хэлперы. Всё сложилось удачно (шаблон можно скачать), в результате обработки данного шаблона получается яваскрипт-файл T4MVC-JS.js, который можно легко инклюдить через тег <script> в хтмле, и так как он генерится не в рантайме и для Visual Studio ничем не отличается от обычного яваскрипт-файла, то по объявленным в нем переменным работает интеллисенс, что сокращает вероятность ошибок.
Read the rest of this entry »

Written by Shaddix

Ноябрь 29th, 2011 at 1:39 пп