Модульність Javascript, MVC та бізнес-реальність на основі сервера


32

Я розумію, що це дуже широке питання, але я працював з різними аспектами цієї проблеми окремо і намагаюся об'єднати всі концепції та технології разом.

Я хотів би вказати, що відповіді повинні включати такі технології:

  • C #
  • MVC 3 w / Бритви
  • Javascript w / jQuery

Все вище та поза ними (наприклад, Backbone.js , Entity Framework тощо) можна отримати в якості пропозицій, якщо вони допоможуть відповісти на питання:

Використовуючи вищеперелічені технології, яка оптимальна стратегія організації коду та логіки при збереженні масштабованості та здатності створювати багатий, швидкий та чистий інтерфейс користувача?

В ідеалі слід зосередити свою увагу на рішенні, що розгортається у бізнес / корпоративному середовищі. Зауважимо, що перелік вище перелічених технологій не буде змінено, тому, будь ласка, не пропонуйте рішення з "ви повинні використовувати xxx замість yyy, якими ви користуєтеся зараз".

Фон

Я щодня працюю з jQuery, приймаю MVC ASP.NET і працюю з C # тривалий час. Таким чином, ви можете представити рішення, припускаючи знання серед цих технологій від середнього до передового.

Я організую це питання на менші частини, щоб спростити відповіді на:

1. Структура проекту

З огляду на те, що я працюю з ASP.NET MVC (у Visual Studio 2010 ), я хотів би вирішити структуру каталогів, яка пропонує деяке прийняття основного макета цього типу додатків. Я думаю, що таке Бранч , але трохи докладніше, що міститиме кожна папка та як вона працює з іншими областями програми.

2. Доступ до даних

Я хотів би максимально модулювати доступ до своїх даних, використовуючи структуру типу API. Можна припустити , безліч об'єктів POCO ( User, UserGroup, Customer, OrderHeader, OrderDetailsі т.д.), але також будуть кілька складних звітами , які вимагають інтенсивної обробки даних SQL і обережний рендеринг UI. EF + LINQ є фантастичними для перших, але не стільки для останніх. Я не можу знайти те, що, здається, відповідає обом сценаріям, не будучи надмірно складним або надмірно простим.

3. Організація коду на стороні клієнта та надання інтерфейсу користувача

Як і більшість розробників, які вперше збирали jQuery, я потрапив у пастку кодування разом, куди потрібно, але швидко виявив, що він накопичується та стає некрасивим. Хоча я з тих пір перейшов до стрибків і меж, я все ще борюся з модулярізацією свого коду та роботою з різними частинами інтерфейсу, не повторюючи код.

Як приклад, типовий фрагмент коду, який я можу написати, виглядав би так, я прокоментував речі, які мене турбують ( зауважте, що я з тих пір перейшов на використання відкладених AJAX-дзвінків і відокремив фактичні запити даних від маніпуляції з DOM ):

$('#doSomethingDangerous').click(function () {
    // maybe confirm something first
    if (confirm('Are you sure you want to do this?')) {   

        // show a spinner?  something global would be preferred so I don't have to repeat this on every page 
        $('#loading').show();  

        // maybe the page should notify the user of what's going on in addition to the dialog?
        $('#results').show().html('<h2>Please wait, this may take a while...</h2>');  

        $.ajax({
            url: 'blah/DoDangerousThing',
            success: function (data) {                     
                // The results will be loaded to the DOM obviously, is there a better way to pull this type of specific code out of the data access calls?
                $('#results').empty();
                $('#results').append('<b>' + data.length + '</b> users were affected by this dangerous activity');
                $('#results').append('<ul>');

                // I've recently started to use jQuery templates for this sort of logic, is that the way to go?
                $(data).each(function (i, user) {
                    $('#results').append('<li>' + user.Username + '</li>');
                });                    
                $('#results').append('</ul>');

                // Need to hide the spinner, again would prefer to have this done elsewhere
                $('#loading').hide();
            }
        });
    }
});

Загальні питання

  • Клієнт MVC проти сервера MVC? Мій проект вже є структурою MVC на стороні сервера, тож чи існує ще потреба у клієнтському MVC, як передбачено Backbone.js?
  • Чи слід створювати файли Javascript для кожного об’єкта (як-от OrderHeader.js), а потім мінімізувати / об'єднувати під час збирання? Або просто має бути Order.jsлогіка для OrderHeader, OrderDetails, Reportsтощо?
  • Як слід обробляти складні запити? Наразі моя провідна теорія є /Reports/Orders-By-Date/чимось таким чином, і я використовую спеціальний SQL-запит, який надає користувальницький набір даних (або ViewModel) у вигляд Razor. А як щодо підкачки, сортування тощо? Це краще зробити клієнтом чи сервером? (припустимо, більший набір даних - запит SQL від 2 до 3 секунд)
  • Я читав проект "Шовк" Microsoft . Це хороший шлях? Як це порівняти з Backbone.js чи іншими?
  • Я дуже звик до багатоярусної архітектури, чи ці поняття дещо викидають це у вікно? Здається, MVC - це як купа міні-N-ярусних секцій у межах того, що було б передній або верхній ярус у минулому.

Знову ж таки, чим конкретніші ваші відповіді, тим краще вони будуть. Я прочитав багато документації та прикладів високого рівня , намагаюся краще зрозуміти переклад її на приклади реального світу .


2
Ви докладаєте багато зусиль у цьому питанні, але це для мене просто не схоже на питання Стакковержа. Можливо, програміст stackexchange стане кращим.
Pointy

3
Я не погоджуюся з тим, що це цікава тема, але Stackoverflow повинен стосуватися об'єктивних питань. Щось подібне до цього питання - це в основному дитина-постер для запитань, які "ймовірно вимагають думки, дебатів, аргументів, опитування чи розширеного обговорення".
Точковий

8
Є табір людей, які планують найбільший масштаб весь час, поки я тихо забираю їхній бізнес, бо вони зайняли занадто довге планування чогось, що ніколи не бувало.
Джейсон Себрінг

1
Я погоджуюся з @Pointy, що це належить до стеку Programmers. Ваше запитання дуже цікаве, і я буду його робити, тому що я завжди шукаю поради. Але це не об'єктивне питання, а закінчується лише пільговими дебатами. Як завжди, робіть те, що найкраще підходить для вашої ситуації ... ніхто з нас нічого не знає про вашу мережеву структуру, кількість клієнтів або статистику трафіку чи процес побудови ... тож питання БУДЬ занадто розпливчастий ... все, що я знаю, це уникати Шовку. ;)
one.beat.consumer

1
Це питання відповідає самому визначенню "надмірно широкого" і, отже, "не справжнього питання". Якщо що-небудь, то окремі питання слід задавати як індивідуальні запитання з деяким незначним досвідом (занадто багато, і люди позначать це "не справжнім питанням"). Однак будьте обережні, деякі окремі запитання, які ви задаєте, ймовірно, будуть позначені як "неконструктивні" самі по собі, тому я буду обережним, як ви ставите ці запитання.
casperOne

Відповіді:


10

TerryR мій друг, ми з вами повинні випити. У нас є деякі подібні проблеми.

1. Структура проекту: Я погоджуюся з Едуардо, що структура папок у додатку MVC залишає бажати кращого. У вас є стандартні папки Контролери, Моделі та Перегляди. Але потім папка Views розбивається на іншу папку для кожного контролера, а також загальну папку. І кожне View / ControllerName або Views / Shared можна розділити на EditorTemplates та DisplayTemplates. Але це дозволяє вам вирішити, як упорядкувати папку "Моделі" (ви можете робити з підпапками та додатковими оголошеннями простору імен).

Не дай Бог, ви використовуєте Області, які копіюють структуру папок Контролери, Моделі та Погляди для кожної області.

/Areas
    /Area1Name
        /Controllers
            FirstController.cs
            SecondController.cs
            ThirdController.cs
        /Models
            (can organize all in here or in separate folders / namespaces)
        /Views
            /First
                /DisplayTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                /EditorTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                PartialViewAbc.cshtml <-- to be used by FirstController
            /Second
                PartialViewDef.cshtml <-- to be used by SecondController
            /Third
                PartialViewMno.cshtml <-- to be used by ThirdController
            /Shared
                /DisplayTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                /EditorTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                PartialViewXyz.cshtml <-- to be used anywhere in Area1
            _ViewStart.cshtml <-- area needs its own _ViewStart.cshtml
            Web.config <-- put custom HTML Helper namespaces in here
        Area1NameRegistration.cs <-- define routes for area1 here
    /Area2Name
        /Controllers
        /Models
        /Views
        Area2NameRegistration.cs <-- define routes for area2 here

/Controllers
    AccountController.cs
    HomeController.cs
/Models
/Views
    /Account
        /DisplayTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        /EditorTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        PartialViewGhi.cshtml <-- to be used by AccountController
    /Home
        (same pattern as Account, views & templates are controller-specific)
    /Shared
        /DisplayTemplates 
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        /EditorTemplates
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        _Layout.cshtml <-- master layout page with sections
        Error.cshtml <-- custom page to show if unhandled exception occurs
    _ViewStart.cshtml <-- won't be used automatically in an area
    Web.config <-- put custom HTML Helper namespaces in here

Це означає, що якщо ви працюєте з чимось на зразок WidgetController, вам потрібно шукати в інших папках, щоб знайти пов’язані WidgetViewModels, WidgetViews, WidgetEditorTemplates, WidgetDisplayTemplates тощо. Наскільки це громіздко, я дотримуюся цього і не відхиляюся від цього. ці конвенції MVC. Що стосується розміщення моделі, контролера та перегляду в одній папці, але з різними просторами імен, я уникаю цього, оскільки використовую ReSharper. Він чітко підкреслить простір імен, який не відповідає папці, де знаходиться клас. Я знаю, що міг би вимкнути цю функцію R #, але вона допомагає в інших частинах проекту.

Для файлів, що не належать до класу, MVC видає вміст та сценарії з коробки. Ми намагаємось зберегти всі наші статичні / некомпільовані файли в цих місцях, щоб знову дотримуватися конвенції. Кожен раз, коли ми включаємо бібліотеку js, яка використовує теми (зображення та / css), усі файли тем переходять кудись під / вміст. Щодо сценарію, ми просто вкладаємо їх у / скрипти. Спочатку це було отримати JS intellisense від VS, але тепер, коли ми отримуємо JS intellisense від R # незалежно від розміщення в / скриптах, я думаю, ми могли б відхилитися від цього і розділити сценарії за папкою для кращої організації. Ви використовуєте ReSharper? ІМО чистого золота.

Ще один невеликий шматочок золота, який дуже допомагає при рефакторингу, - це T4MVC. Використовуючи це, нам не потрібно вводити рядкові шляхи для назв областей, імен контролерів, імен дій, навіть файлів у вмісті та скриптах. T4MVC сильно набирає для вас усі чарівні струни. Ось невеликий зразок того, як ваша структура проекту не має великого значення, якщо ви використовуєте T4MVC:

// no more magic strings in route definitions
context.MapRoutes(null,
    new[] { string.Empty, "features", "features/{version}" },
    new
    {
        area = MVC.PreviewArea.Name,
        controller = MVC.PreviewArea.Features.Name,
        action = MVC.PreviewArea.Features.ActionNames.ForPreview,
        version = "december-2011-preview-1",
    },
    new { httpMethod = new HttpMethodConstraint("GET") }
);

@* T4MVC renders .min.js script versions when project is targeted for release *@
<link href="@Url.Content(Links.content.Site_css)?r=201112B" rel="stylesheet" />
<script src="@Url.Content(Links.scripts.jquery_1_7_1_js)" type="text/javascript">
</script>

@* render a route URL as if you were calling an action method directly *@
<a href="@Url.Action(MVC.MyAreaName.MyControllerName.MyActionName
    (Model.SomeId))">@Html.DisplayFor(m => m.SomeText)</a>

// call action redirects as if you were executing an action method
return RedirectToAction(MVC.Area.MyController.DoSomething(obj1.Prop, null));

2. Доступ до даних: Я не маю досвіду роботи з PetaPoco, але впевнений, що це варто перевірити. Чи розглядали ви складні звіти послуги звітування SQL Server? Або ти працюєш на іншому db? Вибачте, мені не ясно, що саме ви просите. Ми використовуємо EF + LINQ, але також докладаємо певні знання про те, як генерувати звіти в доменних класах. Таким чином, ми маємо сховище дзвінків службових викликів контролера замість того, щоб мати сховище викликів контролера безпосередньо. Для спеціальних звітів ми використовуємо служби звітування SQL, що знову ж таки не є ідеальним, але нашим користувачам подобається легко вносити дані в Excel, і SSRS робить це нам легко.

3. Організація коду на стороні клієнта та надання інтерфейсу користувача: саме там, на мою думку, я можу запропонувати допомогу. Візьміть сторінку з книги ненав’язливої ​​перевірки MVC та ненав'язливого AJAX. Врахуйте це:

<img id="loading_spinner" src="/path/to/img" style="display:none;" />
<h2 id="loading_results" style="display:none;">
    Please wait, this may take a while...
</h2>
<div id="results">
</div>
<input id="doSomethingDangerous" class="u-std-ajax" 
    type="button" value="I'm feeling lucky" 
    data-myapp-confirm="Are you sure you want to do this?"
    data-myapp-show="loading_spinner,loading_results" 
    data-myapp-href="blah/DoDangerousThing" />

На даний момент ігноруйте функцію успіху ajax (докладніше про це пізніше). Ви можете піти з одним сценарієм для деяких своїх дій:

$('.u-std-ajax').click(function () {
    // maybe confirm something first
    var clicked = this;
    var confirmMessage = $(clicked).data('myapp-confirm');
    if (confirmMessage && !confirm(confirmMessage )) { return; } 

    // show a spinner?  something global would be preferred so 
    // I dont have to repeat this on every page 
    // maybe the page should notify the user of what's going on 
    // in addition to the dialog?
    var show = $(clicked).data('myapp-show');
    if (show) {
        var i, showIds = show.split(',');
        for (i = 0; i < showIds.length; i++) {
            $('#' + showIds[i]).show();
        }
    }

    var url = $(clicked).data('myapp-href');
    if (url) {
        $.ajax({
            url: url,
            complete: function () {                     
                // Need to hide the spinner, again would prefer to 
                // have this done elsewhere
                if (show) {
                    for (i = 0; i < showIds.length; i++) {
                        $('#' + showIds[i]).hide();
                    }
                }
            }
        });
    }
});

Вищевказаний код дбає про підтвердження, показує спінер, показує повідомлення очікування та приховує повідомлення спінера / очікування після завершення виклику Ajax. Ви налаштовуєте поведінку за допомогою атрибутів data *, як ненав'язливі бібліотеки.

Загальні питання

- Клієнт MVC проти сервера MVC? Я не намагався бібліотезувати дії, які ви здійснили у функції успіху, бо, схоже, ваш контролер повертає JSON. Якщо ваші контролери повертають JSON, ви можете подивитися на KnockoutJS. Сьогодні вийшов Knockout JS версії 2.0 . Він може підключатися прямо до вашого JSON, так що помітний клацання може автоматично прив’язувати дані до ваших шаблонів javascript. З іншого боку, якщо ви не заперечуєте проти того, щоб ваші методи дій ajax повернули HTML замість JSON, вони можуть повернути вже сконструйований UL зі своїми дочірніми LI, і ви можете додати його до елемента, використовуючи data-myapp-response = "результати". Тоді ваша функція успіху виглядатиме так:

success: function(html) {
    var responseId = $(clicked).data('myapp-response');
    if (responseId) {
        $('#' + responseId).empty().html(html);
    }
}

Підводячи підсумок моєї найкращої відповіді на це, якщо ви повинні повернути JSON з ваших методів дій, ви пропускаєте подання на стороні сервера, тому це дійсно не MVC сервера - це просто MC. Якщо ви повертаєте PartialViewResult з html на виклики ajax, це сервер MVC. Тож якщо ваша програма повинна повертати дані JSON для дзвінків Ajax, використовуйте клієнтський MVVM, як KnockoutJS.

Так чи інакше, мені не подобається розміщений вами JS, оскільки він змішує ваш макет (html-теги) з поведінкою (асинхронна навантаження даних). Вибір сервера MVC з частковими переглядами html або клієнтського MVVM з чистими даними перегляду JSON viewmodel вирішить цю проблему для вас, але побудова DOM / HTML у JavaScript вручну порушує розділення проблем.

- Створення файлів Javascript. Очевидно, що функції мінімізації надходять у .NET 4.5 . Якщо ви проходите ненав’язливим шляхом, це не повинно перешкоджати завантаженню всіх ваших JS в 1 файл сценарію. Я буду обережно створювати різні файли JS для кожного типу об'єкта, ви закінчите вибух файлів JS. Пам'ятайте, щойно ваш файл сценарію завантажується, браузер повинен кешувати його для майбутніх запитів.

- Складні запити, які я не вважаю такими, як складова сторінки, сортування, тощо, як складні. Моя перевага - це обробляти це за допомогою URL-адрес та логіки на стороні сервера, щоб максимально обмежити запити db. Однак ми розміщені в Azure, тому для нас важлива оптимізація запитів. Наприклад: /widgets/show-{pageSize}-per-page/page-{pageNumber}/sort-by-{sortColumn}-{sortDirection}/{keyword}. EF та LINQ для сутностей можуть обробляти пагинацію та сортування за допомогою таких методів, як. Я ще не знайшов потреби у клієнтськійлібі, тому я, чесно кажучи, не знаю багато про них. Подивіться на інші відповіді, щоб отримати більше порад щодо цього.

- Шовк проекту Ніколи про це не чув, доведеться його перевірити. Я великий шанувальник Стіва Сандерсона, його книг, його BeginCollectionItem HtmlHelper та його блогу. Це означає, що я не маю досвіду роботи з KnockoutJS у виробництві . Я перевірив його підручники, але намагаюся не брати на себе зобов’язання, поки це не принаймні версія 2.0. Як я вже згадував, KnockoutJS 2.0 щойно вийшов.

- N-ярус Якщо під рівнем ви маєте на увазі різні фізичні машини, то ні, я не думаю, що нічого не виходить із вікон. Як правило, 3-х рівневий означає, що у вас є 3 машини. Таким чином, у вас може бути жирний клієнт, як ваш рівень презентації, який працює на машині користувача. Клієнт жиру може отримати доступ до рівня обслуговування, який працює на сервері додатків і повертає XML або будь-який інший товстий клієнт. І сервісний рівень може отримувати свої дані з SQL-сервера на 3-й машині.

MVC - це один шар, на 1 ярусі. Ваші контролери, моделі та види - це частина вашого шару презентації, який є 1 рівнем фізичної архітектури. MVC реалізує модель Model-View-Controller, де ви можете бачити додаткові шари. Однак намагайтеся не розглядати ці 3 аспекти як яруси або шари. Спробуйте подумати про всі 3 з них як про ступінь презентаційного рівня.

Оновлення після прес / шини / коментаря до даних

Гаразд, значить, ви використовуєте рівень і шар безперервно. Зазвичай я використовую термін "шар" для розділів логічного / проекту / складання, а рівень для фізичного розділення мережі. Вибачте за непорозуміння.

У таборі MVC ви знайдете досить багато людей, які кажуть, що не слід використовувати "Моделі" в MVC для вашої моделі даних, а також не використовувати контролери для бізнес-логіки. В ідеалі ваші моделі повинні бути ViewModels, орієнтовані на перегляд. Використовуючи щось на кшталт Automapper, ви берете свої об'єкти з вашої доменної моделі та переносите їх у ViewModels, скульптурну спеціально для використання у представленні.

Будь-які бізнес-правила також повинні бути частиною вашого домену, і ви можете їх реалізувати, використовуючи доменні служби / заводський зразок / все, що підходить у вашому доменному шарі, а не в шарі презентації MVC. Контролери повинні бути тупими, хоча і не настільки німими, як моделі, і повинні відповідати домену за все, що вимагає ділових знань. Контролери управляють потоком HTTP-запитів та відповідей, але все, що має реальну ділову цінність, повинно бути вище рівня оплати контролера.

Таким чином, ви все ще можете мати шарувату архітектуру, з MVC як презентаційний шар. Це клієнт рівня вашого додатка, рівня обслуговування або доменного рівня, залежно від способу його архітектури. Але в кінцевому рахунку модель вашої сутності повинна бути частиною домену, а не моделями в MVC.


Я повністю згоден з цією відповіддю! Особливо: • Resharper - геній MVC ... від перевірки помилок до навігації IDE, її корисність мене відштовхує! • MVC на стороні сервера майже завжди є найкращим підходом. • MVC не є 3-ма окремими рівнями, це єдиний рівень презентації - я ніколи не думав про це таким чином, але це абсолютно правильно.
Скотт Ріппей

Дуже приємна відповідь, безумовно, що я шукав ціною моїх 300 представників. Напої на мене, якщо ви знаходитесь в районі Торонто :)

btw Я завжди розглядав N-рівень як Pres / Bus / Data незалежно від того, де вони фізично сиділи. Тому я сказав, що MVC майже видаляє цю архітектуру, оскільки вона в основному поєднує 3, те, що ви сказали, дещо погоджується з цим, але також надає інший погляд на це.

Я б застеріг від ViewModel, модель за переглядом, підхід. Нещодавно я натрапив на ситуацію, коли пізніше побажав, щоб у мене не було цього абстрагування від DTO до ViewModel. Див: stackoverflow.com/q/7181980/109456

Як правило, мені не подобається бачити jQuery і замість цього пишуть об'єкти з інтерфейсами, які будь-який розробник на стороні сервера міг би досить швидко зрозуміти за допомогою JQ або API DOM, що веде бізнес всередині. Мені також дуже подобається концепція Django URLConfig і я вважаю її корисною для встановлення об’єктів для реалізації на сторінках. Я поняття не маю, що таке МВ? Бібліотеки, як передбачається, для мене. Вони не ідеально підходять для вирішення проблеми, IMO та делегація подій DOM + - це все, що мені потрібно для обробки сторінок, не надто прив’язаних до конкретної структури.
Ерік Реппен

6

Я не збираюся писати повної відповіді, але хочу поділитися порадами.

Мої поради:

1. Структура проекту
Я виявив, що структура MVC за замовчуванням для мене не підходить. Я, як правило, працюю в контролері, поглядах і моделі одного і того ж об'єкта (думаю, товар, замовлення, клієнт) одночасно. Отже, мені подобається мати файли в одній папці, але з різними просторами імен.

2. Дані
Якщо ви перейдете з Linq-to-SQL або EF, ви пошкодуєте пізніше.
Я використовую PetaPoco, який дозволяє мені запускати SQL, витягуючи та оновлюючи записи, без болю при картографуванні, але не вивчаючи нового способу робити речі і без кошмарів продуктивності.

У мене є генератор коду для створення початкового класу POCO з атрибутами PetaPoco, а потім зміна класу, коли якесь поле додається чи видаляється.

PetaPoco працює з динамічними та стандартними класами, тому у вас немає ніяких компромісів (Massive - це все динамічно, а Dapper - всі стандартні класи)

Я також генерую головний SQL, використовуючи вбудований SqlBuilder, який містить усі стандартні об'єднання для сутності, але немає WHERE, тому я повторно використовую той самий SQL для отримання однієї сутності чи списку.

3. Jquery Ви можете стандартизувати деякі частини інтерфейсу, використовуючи загальний дзвінок jQuery (заповнення деяких даних всередині елемента HTML).

Наприклад, у мене є це для видалення.

var deleteLinkObj;
// delete Link
$('.jbtn-borrar').click(function () {
    deleteLinkObj = $(this);  //for future use
    $('#delete-dialog').dialog('open');
    return false; // prevents the default behaviour
});
$('#delete-dialog').dialog({
    autoOpen: false, width: 400, resizable: false, modal: true, //Dialog options
    buttons: {
        "Borrar": function () {
            $.post(deleteLinkObj[0].href, function (data) {  //Post to action
                if (data == 'OK') {
                    deleteLinkObj.closest("tr").hide('fast'); //Hide Row
                }
                else {
                    alert(data);
                }
            });
            $(this).dialog("close");
        },
        "Cancelar": function () {
            $(this).dialog("close");
        }
    }
});

Мені просто потрібно додати клас jbtn-borrarдо гіперпосилання, і він відображає діалогове вікно, видаляє запис і приховуєtr

Але не передумуйте. Ваш додаток буде сяяти невеликими штрихами в кожному перегляді.

Клієнт MVC проти сервера MVC
Server MVC. Скористайтеся частковими переглядами, які ви можете використовувати в початковій візуалізації та оновіть деякі частини Ajax, використовуючи той самий вигляд. Дивіться цю чудову статтю

Як слід обробляти складні запити (дозволяємо називати це Звіт)
Я використовую клас, у якому параметри звіту є властивостями (зручно для автоматичного автоматичного використання MVC) та Generateметод, який виконує запит і заповнює список спеціального класу (якщо ви не не мати класу, який відповідає ViewModel)
Ви можете використовувати цей клас як модель перегляду та заповнити таблицю створеним списком.

Проект Microsoft «Шовковий проект»
надрукований. Бігайте так швидко, як тільки можете у зворотному напрямку.


Смішно, коли я читав проект «Шовк», я продовжував отримувати це неприємне відчуття, і я не міг його розмістити. Можливо, це було ...

3

1. Структура проекту

У моєму рішенні є 2 файли проекту

1) Сервісний / бізнес-рівень Я розміщую всю свою логіку бізнесу та код доступу до БД та POCO в цей окремий проект. Немає необхідності в рівні доступу до даних, якщо ви використовуєте ORM як ORM, вже абстрагуєте рівень DB.

2) Шар інтерфейсу містить усі мої перегляди, контролери, моделі, скрипти, CSS

Я намагаюся змусити мої контролери, перегляди, сценарії та CSS використовувати схожу структуру папок. Також структуруйте мої файли так, щоб максимально відповідати URL-адресу. Щоб уникнути необхідності писати власну маршрутизацію.

Максимально використовуйте DisplayTemplates, EditorTemplates, Parcial Views та папку Shared.

Потім я структурую всі мої скрипти так, щоб вони відповідали тим самим областям, контролерам моїх файлів c #, тому я мав би файл root.js у корені js-файл на сторінку та файл common.js для кожної області.

CSS-файли У мене зазвичай є 2 + n (де n - кількість областей) 1-й файл CSS - це CSS лише для цільової сторінки, щоб допомогти швидше завантажувати сторінку (можливо, це не так важливо для ділового та корпоративного середовища) 2-й файл CSS це common.css, який містить усі стилі для всіх інших сторінок. Потім ще один файл common.css для кожної області, наприклад, файл AdminArea.css, у якому є CSS для кожної сторінки адміністратора.

2. Доступ до даних

Якщо я використовую Entity Framework, я використовую CodeFirst, оскільки він дуже добре працює з POCOS, і у вас немає моделі для обслуговування. nГібернат набагато потужніший, але має більш сувору криву навчання. Для підкачки результатів базу даних у мене є утиліта c # class багаторазового використання та прохідний вигляд, який я використовую для всіх своїх переглядів.

Для складних запитів та генерування звітів використовую збережені процедури. Вони набагато простіше писати та підтримувати та пропонують більшу потужність LINQ. Вони також можуть бути повторно використані іншими службами, такими як SSRS. Я використовую автоматизатор для перетворення набору даних, повернених назад, до тих самих стандартних рам POCO.

3. Організація коду на стороні клієнта та надання інтерфейсу користувача

Відповідь Едуардо Молтені має хороший приклад коду. Крім того, я б точно рекомендував використовувати knockoutjs, оскільки він має і гарні шаблони, і прив’язки. Якщо ви використовуєте JSON для всіх своїх дзвінків AJAX, які я використовую дуже багато, то наявність автоматичної карти UI на об'єкти JS - це величезна економія часу.

Загальні питання

Складні запити повинні жити в збереженій програмі. (див. коментар emeraldcode.com)

Ви все ще зберігаєте свою N-ярусну архітектуру за допомогою цього MVC.


1

Нещодавно я переконаний, що якщо ви плануєте використовувати три перераховані вище технології, слід спочатку почати з прийняття Orchard CMS . Я вважаю, що це найкраща однозначна відповідь на Вашу центральну вимогу:

Яка оптимальна стратегія організації коду та логіки при збереженні масштабованості та здатності створювати багатий, швидкий та чистий інтерфейс користувача?

У сценарії Очарда все, до чого ви не можете звертатися через його механізми налаштування, ви б потім обробляли або шляхом додавання безкоштовних онлайн-модулів, або написання власного модуля (що, звичайно, є C #, бритвою, тощо). Організація коду - сила Орчарда.

Що стосується доступу до даних, то для повноцінного ORM є достатньо плюсів і мінусів, і я теж вважаю, що мікро-ORM - це найкраще. Спробуйте Massive або Dapper . Обидва були представлені на Hanselminutes . Я підсумую їх, кажучи так: абстракції від SQL майже незмінно руйнуються в міру збільшення проекту. Зрештою, найкращим рішенням для доступу до БД є ця абстракція під назвою SQL (трохи сарказму, але правда). Нехай мікро-ОРМ працює з цим, і у вас є золото.

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


0

Не впевнений, як я пропустив це запитання, але я додав свої два центи через два роки.

Клієнт MVC проти сервера MVC? Мій проект вже є структурою MVC на стороні сервера, тож чи існує ще потреба у клієнтському MVC, як передбачено Backbone.js?

MVC і MV? ще до того, як його відсунули на сторону клієнта, в основному вона перетворилася на маркетинговий термін, який насправді лише обіцяє, що так чи інакше дані будуть відокремлені від інших речей, що за великим рахунком є ​​чудовою ідеєю, але насправді не так складно зробити. Незалежно від того, який підхід ви використовуєте, безпосередньо перед або прямо в середині внесення змін до HTML, які впливають на можливості презентації чи взаємодії, - це абсолютно жахливе місце для розбору того, що бізнес хоче, щоб ви робили дані.

У "логіці перегляду" немає нічого особливого. Цей же принцип повинен застосовуватися до всієї логіки. А це, не робіть нічого зараз, що мало б набагато більше сенсу робити раніше. Коли всі ваші качки стоять поспіль перед тим, як передавати якісь дані або ініціювати новий процес, цей попередній етап, ймовірно, буде набагато більше використаний для всього іншого в системі, що робить щось подібне.

Чи слід створювати файли Javascript для кожного об'єкта (наприклад, OrderHeader.js), а потім мінімізувати / об'єднувати під час збирання? Або просто повинен бути Order.js, який має логіку для OrderHeader, OrderDetails, Reports тощо?

Це дійсно від вас, але я б спробував відійти від однофайлової, однокласної речі. Я ніколи не розумів, чому було корисно, наприклад, знайти абстрактний файл та інтерфейс, а також реалізовувати файли тощо ... Класифікуйте по ширших питаннях. ctrl + f не так важко використовувати, якщо він триває трохи довше.

Однак, ніколи не слід рекомбінувати JS, щоб зменшити файли в Інтернеті. Браузери кешують JS, тому ви просто змушуєте перезавантажувати той самий JavaScript, вставляючи старий JS у нові файли. Забороняючи приголомшливі обсяги JavaScript, єдиний раз, коли у вас не має бути всього JS на сторінці, це коли дуже велика кількість його, яка є дуже специфічною для одного розділу сайту без перекриття / сірих ділянок, ніколи не буде потрібна для заданого сторінки.

І FFS не метушиться з управлінням залежностями з JavaScript в Інтернеті. Require.js на веб-сайтах із середньою та низькою складністю змушує мене захоплюватися дитячими тюленями. Вставте сторонні бібліотеки у верхній блок. Ваші власні бібліотеки у другому блоці. І тоді ваш код реалізації (який ніколи не повинен бути десятим, ніж ваш внутрішній бібліотечний код - тобто дуже лаконічний, зрозумілий і простий для розуміння) у цьому третьому пакеті.

Як слід обробляти складні запити? На даний момент моєю провідною теорією є / Звіти / Порядок за датою / або щось подібне, і я використовую спеціальний SQL-запит, який надає користувальницький набір даних (або ViewModel) у вигляд Razor. А як щодо підкачки, сортування тощо? Це краще зробити клієнтом чи сервером? (припустимо, більший набір даних - 2–3 секундні запити SQL), який я читав у проекті Microsoft Silk. Це хороший шлях? Як це порівняти з Backbone.js чи іншими?

Чесно кажучи, я б сказав, що для вас все простіше, що не смердить на клієнта. Веб-сторінки завантажуються досить чортово за сучасними технологіями. Якщо впровадження в Ajax для вас сильно болить, не варто. Просто займіться тим, що ви краще знаєте, а потім зможете пізніше пофантазувати і побачити, як вам це подобається під час пейджингу. Якщо ви будуєте новий складний додаток з нуля, почніть з основного та натисніть пізніше.

Я дуже звик до багатоярусної архітектури, чи ці поняття дещо викидають це у вікно? Здається, MVC - це як купа міні-N-ярусних секцій у межах того, що було б передній або верхній ярус у минулому.

Це насправді залежить від того, хто хто фантазує, що таке МВ? є. ІМО, мікрокосм, як правило, працює дуже добре. Клас віджетів, який розділяє дані, зв’язок та речі, пов’язані із переглядом, всередині чудово працює. В Інтернеті на стороні клієнта найважливіша річ, IMO, полягає у підтримці балансу збереження проблем, розділених без зайвого розбиття на крихітні невеликі проблеми, повторне складання яких ускладнює розуміння та повторне використання та зміну речей. Тут працює чудовий "duh" OOP. Ви не хочете складних процесів. Ви, очевидно, хочете назвати речі, які можна переміщувати і казати робити речі. Ось кілька порад на цьому фронті:

  • KISS, що (OOP) інтерфейс Я не хочу бачити DOM або jQuery чи щось інше, що притиснутий сервер розробник не міг зрозуміти досить швидко в моєму коді реалізації. Все, що повинна знати людина, - це клас клацати по контейнеру div та який перемикати на перевернути, щоб зробити досить загальний набір інтерфейсу користувача активним на даній сторінці. Варіації теми все-таки повинні бути здійснені шляхом передачі добре задокументованих / коментованих об'єктів параметрів, перш ніж вони повинні почати перегляд document.get <anything> або зрозуміти що-небудь, що виходить за межі основних принципів CSS.

  • Гаразд, як це зробити? Ну, ми вже маємо модель. Це називається DOM. І у нас є делегація подій. Якщо ви не розбірливо закриваєте бурхливість подій (не робіть цього - це там, тому що це корисно), ви можете забрати кожного, навіть із тіла, якщо хочете. Потім вивчіть цільове властивість об'єкта переданого події та визначте, хто просто "перетворився". Якщо ви чітко структуруєте документ HTML , немає підстав не використовувати його як модель делегування. Поведінка та структура змісту природно пов'язані. Добре, щоб двоє мали ідентифікатори, що перекриваються.

  • Не платіть за прив'язку даних І під «платою» я, звичайно, маю на увазі «ляпніть бібліотеку на вашу кодову базу, яка наполягає на тому, що ви все робите просто так - весь час, щоб отримати чудо-користь, яку насправді не важко зробити». Система подій JQ робить це досить просто.

Приклад часу:

function PoliticianData(){ //a constructor

    var
        that = this, //I hate 'that' but example so convention

        flavorsOfLie = {

            lies: "Oh Prism? Psh... no we're all good. There's a guy keeping an eye on that.",

            damnedLies: "50% of the people chose to not give a damn when asked whether it was better to let the terrorists win or not give a damn."

        }
    ;//end instance vars

    this.updateLies = function( lieType, newData ){
        flavorsOfLie[lieType] = newData;
        $(that).trigger({type:'update', lieType:lieType, newData: newData });
    }

    //so everytime you use the updateLies method, we can have a listener respond
    //and pass the data
}

var filthyLies = new PoliticianData();

$(filthyLies).on('update', function(e){
    stickNewDataInHTMLWithSomeFuncDefinedElsewhere(e.lieType, e.newData);
} );

filthyLies.update('damnedLies','50% of the people said they didn\'t give a damn');
//oh look, WaPo's front page just changed!
  • Не приховуйте Інтернет . Головне джерело виїмки в усіх ранніх спробах зробити полегшення для клієнта на стороні сервера та розробників додатків, що зациклюються на цій критичній точці. Запити HTTP не є і ніколи не були складними. Їм не потрібно 18! @ # $ Ing шару плутати-подія-ім'я-на кожній стадії жахливості, щоб полегшити розуміння. Крім того, є багато що знати про клієнтську сторону, але немає підстав ховатися від HTML і DOM, який взаємодіє з нею, ляпаючи велику гігантську модель поверх неї. Це вже велика гігантська модель, і вона працює дуже добре. Все, що нам потрібно зробити трохи більш керованим, - це деякі розумні практики OOP та деякі знання JS та DOM.

  • Вигідна гнучкість

EXTjs <==== шкала гнучкості ====> jQuery (не обов'язково будь-який з її плагінів)

ІМО, інструменти, які дозволяють вам швидко робити ЗНО, завжди є кращим вибором. Інструменти, які зробили все для вас, - це лише правильний вибір, коли ніхто над вашою головою не особливо вибагливий щодо деталей, і ви не проти передати контроль над тією справою, яка повинна вам допомогти. Я фактично бачив плагіни, які підтверджують HTML, щоб переконатися, що ви не прокрадаєте інший елемент з усіма такими ж точними ознаками відображення. Чому? У мене є лише теорії. Я думаю, що це доводиться до того, що комплементарі дійсно ненавидять ідею того, щоб хтось використовував свої речі таким чином, який не був призначений, і це завжди неминуче те, що хтось хоче, щоб ви робили в інтерфейсі користувача.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.