- PVSM.RU - https://www.pvsm.ru -

Мост из мира .NET в мир JavaScript

Хочу поделиться интересной находкой — Bridge.net [1]. Если в двух словах, это фреймворк, позволяющий транслировать C# код в JavaScript. Идея, которая движет командой разработчиков очень проста и понятна — транслировать логику настолько идентично, насколько это возможно. Что радует, если вспомнить все различия и специфику этих языков.

Мост из мира .NET в мир JavaScript - 1

Пожалуй, каждый сможет найти свое персональное применение, но я хотел бы отметить те моменты, которые привлекли лично меня:

  • Возможность применения для мобильной разработки. JavaScript работает на всех платформах
  • Применимость для Web. Особенно, если нужно переписать устаревший проект, например, в виде SPA приложения [2]
  • Возможность переиспользовать C# код одновременно на стороне сервера и клиента
  • Трансляция, выполняемая во время сборки проекта
  • Проект находится в стадии активной разработки, есть адекватная поддержка со стороны разработчиков
  • Bridge.net — это OpenSource проект с лицензией на использование в коммерческих целях (лицензия Apache 2.0 [3])

В качестве демонстрации использования Bridge, я хочу поделиться решением задачи валидации полей в Web приложении. Надеюсь, пример будет наглядным, ведь подобная задача может встречаться достаточно часто. Для простоты буду использовать ASP.NET Web Forms.

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

Серверная логика проверки ввода

protected void submitButton_OnClick(object sender, EventArgs e)
{
    var isCorrect = IsCorrectPlateNumber(plateTextBox.Text);
    plateTextBox.BackColor = isCorrect ? Color.LightGreen : Color.Coral;
}
private static bool IsCorrectPlateNumber(string plateNumber)
{
    var success = false;
    if (!string.IsNullOrWhiteSpace(plateNumber))
    {
        plateNumber = plateNumber.Trim();
        if (plateNumber.Length >= 8 || plateNumber.Length <= 9)
        {
            var rgx = new Regex(@"^[АВЕКМНОРСТУХавекмнорстух]d{3}[АВЕКМНОРСТУХавекмнорстух]{2}d{2,3}$");
            success = rgx.IsMatch(plateNumber);
        }
    }
    return success;
}

Мост из мира .NET в мир JavaScript - 2

Хорошо, теперь мы хотим снизить нагрузку на сервер и выполнять валидацию поля на стороне клиента. Вариантов тут несколько:

1) Заново написать клиентскую валидацию, которая будет проверять самые простые сценарии, так сказать, «защита от дурака». Основные проверки будут по-прежнему выполняться на стороне сервера.

Простая клиентская валидация

Рег. номер автомобиля (формат X 000 XX 000):<br/>
<asp:TextBox ID="plateTextBox" runat="server"/>
<asp:Button ID="submitButton" runat="server" Text="Проверить" OnClientClick="return validatePlate();" OnClick="submitButton_OnClick"/>

function validatePlate() {
    var value = document.getElementById('<%=plateTextBox.ClientID%>').value;
    if (value && value.length) {
        return true;
    }
    alert("Введите рег. номер автомобиля!");
    return false;
}

2) Портировать серверную валидацию, насколько это возможно, тем самым повторив код. Плюсы очевидны — минимальное расхождение результатов валидации на сервере и на клиенте. Минусы тоже есть — повторяя серверную логику, хотелось бы также поддерживать ее в актульном состоянии, что может добавить головной боли. Переписывать вручную код не буду, он вполне понятен. Давайте лучше посмотрим, как нам помог бы Bridge. Для этого воспользуемся online редактором [4]. Транслированный код будет выглядеть следующим образом:

Полная клиентская валидация

(function (globals) {
    "use strict";

    Bridge.define('Demo.ServerLogic', {
        statics: {
            isCorrectPlateNumber: function (plateNumber) {
                var success = false;
                if (!Bridge.String.isNullOrWhiteSpace(plateNumber)) {
                    plateNumber = plateNumber.trim();
                    if (plateNumber.length >= 8 || plateNumber.length <= 9) {
                        var rgx = new Bridge.Text.RegularExpressions.Regex("constructor", "^[АВЕКМНОРСТУХавекмнорстух]\d{3}[АВЕКМНОРСТУХавекмнорстух]{2}\d{2,3}$");
                        success = rgx.isMatch(plateNumber);
                    }
                }
                return success;
            }
        }
    });

    Bridge.init();
})(this);

Нам остается подключить файл Bridge.js (для простоты я взял файл скрипта из онлайн редактора), а также немного модифицировать нашу первоначальную функцию валидации:

function validatePlate() {
    var value = document.getElementById('<%=plateTextBox.ClientID%>').value;
    if (Demo.ServerLogic.isCorrectPlateNumber(value)) {
        return true;
    }
    alert("Неверный рег. номер автомобиля!");
    return false;
}

3) Переиспользовать логику. Если мы хотим поддерживать ее в актуальном состоянии, то можно настроить, чтобы трансляция валидации из C# в JavaScript выполнялась при каждой сборке проекта. Таким образом, логика по-настоящему становится переиспользуемой, программисты не тратят свое время попусту, приложение становится стабильнее, а пользователи еще счастливее! Для этого нужно выполнить несколько шагов:

Встраивание Bridge в проект

1. Создадим в имеющемся солюшене проект WebApplication1.Bridge

2. Установим в него Nuget пакет [5]. Устанавливайте этот пакет в отдельный проект, т.к. при установке удаляются конфликтующие References.

Мост из мира .NET в мир JavaScript - 3

3. В проекте WebApplication1 вынесем логику в отдельный файл/класс. Соответственно, теперь этот класс будет использован в обработчике события нажатия на кнопку (изменения понятны, код не привожу).

ServerLogic.cs

using System.Text.RegularExpressions;

namespace WebApplication1
{
    public class ServerLogic
    {
        public static bool IsCorrectPlateNumber(string plateNumber)
        {
            var success = false;
            if (!string.IsNullOrWhiteSpace(plateNumber))
            {
                plateNumber = plateNumber.Trim();
                if (plateNumber.Length >= 8 || plateNumber.Length <= 9)
                {
                    var rgx = new Regex(@"^[АВЕКМНОРСТУХавекмнорстух]d{3}[АВЕКМНОРСТУХавекмнорстух]{2}d{2,3}$");
                    success = rgx.IsMatch(plateNumber);
                }
            }
            return success;
        }
    }
}

4. Добавим созданный файл в проект WebApplication1.Bridge как ссылку [6]

5. Изменим output директорию для проекта WebApplication1.Bridge. Для этого настроим в файле bridge.json:

"output": "../WebApplication1/Scripts/Bridge"

6. После сборки в Solution Explorer нажмем Show All Files и сможем увидеть сгенерированный скрипт webApplication1.js

7. Добавим нужные ссылки и обновим скрипты на странице Demo.aspx:

Demo.aspx скрипты

<script src="Scripts/Bridge/bridge.js" type="text/javascript"></script>
<script src="Scripts/Bridge/webApplication1.js" type="text/javascript"></script>
<script type="text/javascript">
function validatePlate() {
    var value = document.getElementById('<%=plateTextBox.ClientID%>').value;
    if (WebApplication1.ServerLogic.isCorrectPlateNumber(value)) {
        return true;
    }
    alert("Неверный рег. номер автомобиля!");
    return false;
}
</script>

8. Всё. Можно собирать проект и запускать. Теперь любые изменения в логику валидации будут автоматически работать как для серверной проверки, так и для клиентской.

Так, на простом примере, мы увидели как можно легко переиспользовать C# код, даже когда это нужно сделать с помощью JavaScript. И что может представлять бОльшую ценность — как такой подход встраивается в процесс разработки и сборки Web приложения. Однако, это не единственное преимущество Bridge.net. Я вижу его неоспоримым помощником в кроссплатформенной мобильной разработке, особенно для тех, кто не представляет свою жизнь без .NET'а, но об этом в следующий раз!

Автор: devsane

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/c-2/317022

Ссылки в тексте:

[1] Bridge.net: http://bridge.net/

[2] SPA приложения: https://en.wikipedia.org/wiki/Single-page_application

[3] лицензия Apache 2.0: https://github.com/bridgedotnet/Bridge/blob/master/LICENSE

[4] online редактором: https://deck.net/b1bf609488ef8f167543afa188ef8944

[5] Nuget пакет: https://www.nuget.org/packages/Bridge

[6] как ссылку: https://msdn.microsoft.com/en-us/library/windows/apps/jj714082(v=vs.105).aspx

[7] Источник: https://habr.com/ru/post/450990/?utm_campaign=450990